What I want is to be able to access the two JSON arrays with my PHP method, and that is where I am drawing a blank.
I tried sending the entire form as a FormData object, as @m3g4p0p suggested, but it only sends the original form data, not the values from the dynamically created form elements, which is what happens normally when you submit the form. That’s why I converted the JS-created elements into a JSON array to grab and keep the data from them, separately from the regular part of the form.
Originally, I had done this all with PHP. So I submitted the form, along with the number of ingredients and directions, and the new form elements were created in a different form after a page refresh. Then I had to submit that to get the ingredients and directions. I found that to be very clunky, which is why I am trying to learn how to integrate JavaScript into the process.
Well, you were putting together a formdata, which was going to use AJAX to send it
If you want to use FormData to send the AJAX request, take a look at the MDN examples for a general idea of how the flow goes. Also at the bottom of that page is another link to explain just using the XMLHttpRequest object (The thing that actually DOES the AJAX)
I have a form for adding a recipe to my application. Every recipe has a different number of ingredients and directions, so I wanted to make that part dynamic. Most of the form is just a plain old form, but the dynamic number of elements for ingredients and directions (which will go in a database table of their own, because it is a one-to-many relationship) is the JavaScript part of it. And when I add those elements dynamically, my $_POST array won’t pick up their values along with the rest of the form values. So I’m trying to figure out how to get them separately to my PHP for processing.
I used JSON because I know that both JavaScript and PHP can handle it - so that was going to be my bridge between the two, but I’m missing a number of steps.
But I have all that. See my first post to get a list of what I have already done. Because the inputs are dynamically added using JavaScript, when I submit my form, only the original form elements (e.g. name, description, preparation time, cooking time, etc) send their values to the $_POST array, not these ones. So I used JavaScript to grab their values and put them in two arrays - one for ingredients, and one for directions. And it is these two arrays that I can’t figure out how to get into my controller to be read and processed by PHP. I’m sorry if the description in my first post was not clear. I thought it described what I had accomplished and what I was trying to accomplish as my next steps…
const numIngredients= document.getElementById("num_ingredients");
let numIngred;
const numDirections = document.getElementById("num_directions");
let numDir;
let submitBtn = document.getElementById("submit");
numIngredients.addEventListener('input', (event) => {
// dynamically add inputs to ingredients based on number of ingredients entered
let ingredientInputs = "";
numIngred = numIngredients.value;
let counter = 0;
for (let i = 0; i < numIngred; i++) {
counter = i + 1;
ingredientInputs += '<li><input type="text" name="ingredients[]" id="ingredients' + counter + '" class="medium-textbox"></li>';
}
document.getElementById("ingredients").innerHTML = ingredientInputs;
event.preventDefault();
// Add all the ingredients from the form inputs into a JS array
let ingredArr = addIngredientsToArray();
});
numDirections.addEventListener('input', (event) => {
// dynamically add textareas to directions based on number of directions entered
let directionInputs = "";
numDir = numDirections.value;
let counter = 0;
for (let i = 0; i < numDir; i++) {
counter = i+1;
directionInputs += '<li><label>' + counter +'. </label> <textarea name="directions[]" id="directions' + counter + '"></textarea></li>';
}
document.getElementById("directions").innerHTML = directionInputs;
event.preventDefault();
let dirArr = addDirectionsToArray();
});
// add ingredients form values to a JS array
// ingredients ordered list has id of 'ingredients'
function addIngredientsToArray() {
let ingredientsArray = [];
let jsonIngredients = {};
let ingredientsInputs = document.getElementById("ingredients")
.getElementsByTagName('input');
for (let i = 0; i < ingredientsInputs.length; i++) {
ingredientsInputs[i].addEventListener('change', (event) => {
ingredientsArray.push(ingredientsInputs[i].value);
});
}
// add all the ingredients from the form inputs into a JS array
submitBtn.addEventListener('change', (event) => {
jsonIngredients = JSON.stringify(ingredientsArray);
});
sendJsonArrays(jsonIngredients);
// return jsonIngredients;
}
// add directions form values to a JS array
// directions ordered list has id of 'directions'
function addDirectionsToArray() {
let directionsArray = [];
let jsonDirections = {};
let directionsTextareas = document.getElementById("directions")
.getElementsByTagName('textarea');
for (let i = 0; i < directionsTextareas.length; i++) {
directionsTextareas[i].addEventListener('change', (event) => {
directionsArray.push(directionsTextareas[i].value);
});
}
// add all the directions from the form textareas into a JS array
submitBtn.addEventListener('change', (event) => {
jsonDirections = JSON.stringify(directionsArray);
});
sendJsonArrays(jsonDirections);
// return jsonDirections;
}
// call the functions that convert the ingredients, directions array to JSON
let jsonIngredients = addIngredientsToArray();
let jsonDirections = addDirectionsToArray();
// Use formData to send JSON to php controllers
function sendJsonArrays(jsonArray) {
let formData = new formData();
formData.append(jsonArray);
console.log(formData);
let request = new XMLHttpRequest();
}
The last function is a work in progress - my attempt at trying to follow some suggestions provided here - it is not finished.
Your HTML is incorrect. It basically looks like this:
<div class="left-content">
<form action="/recipes/add" method="post">
<!-- lots of form fields here -->
</div>
<div class="right-content">
<!-- ingredients and directions here -->
</div>
</form>
Browsers will see: okay, so we start a div, then we start a form, then we close a div - hey hold on, there is form still open here, I can’t just leave that hanging, so I’ll close that as well. So it’s basically interpreted as
<div class="left-content">
<form action="/recipes/add" method="post">
<!-- lots of form fields here -->
</form> <!-- Form closed implicitly by browser here -->
</div>
<div class="right-content">
<!-- ingredients and directions here -->
</div>
</form>
So the ingredients and the directions are not part of the form, and will not be sent to the server.
So what you should do instead is:
<form action="/recipes/add" method="post">
<div class="left-content">
<!-- lots of form fields here -->
</div>
<div class="right-content">
<!-- ingredients and directions here -->
</div>
</form>
And the form closes around your ingredients and directions as well, and you will receive them in $_POST when you submit the form.
Oops! I didn’t even see that. That is left over from when I had the separate form to just deal with the ingredients and directions. I removed that and put the two together and left the one closing form tag in by mistake. Thank you for seeing that. So I went through all that JavaScript and led everyone down the proverbial garden path for nothing? I’m feeling a bit dumb right now.
It did work now. :sigh Well, I did learn a lot from all the contributors to this thread, and intend to look further into Ajax and the XMLHttpRequest object (after I come out from hiding).