I am developing a web application using Laravel and jQuery.
There is a parent Laravel blade that contains a form.
The form contains checkboxes to chose combinations of two object types A and B.
The change of checkboxes trigger an AJAX request which replaces the content of a div container inside the form with another embedded Laravel blade.
The contents of the embedded Laravel blade are dependent on the combinations of chosen objects of type A and B.
An object of type B has parameters whose values should be set via radio buttons in the embedded Laravel blade.
The combination of one object of A, one object of B and a combination of parameter values for parameters of object B are contained in one div in the embedded blade.
How do I add an ‘add’ button in the embedded blade per combination of object A and object B to enable configuration for more than one combination of parameter values for object A and object B?
See code snippets below. I tried to boil it down to the essential.
I came up with dynamic individual HTML IDs for div container and ‘add’ button for a combination of object A and object B in embedded.blade.php.
Then I wanted to reference these dynamic IDs with jQuery to register an event per ‘add’-Button that adds HTML containing PHP variables in the right div container.
When I run the whole thing it throws no errors but when I click on any of the ‘add’ buttons the new HTML is not appended to the corresponding div but to only one of the divs in the embedded blade.
That might be due to the fact that the referencing of the dynamic IDs does not work as I expect it to.
It seems to me that only the last element of each of the two arrays respectively the values of the last iteration of the loops in the tag of embedded.blade.php are used for my prefix variable.
Is it even good practice to use dynamically generated HTML IDs? Or is it bad practice, should I avoid it?
Especially in the context of referencing them by jQuery?
Do I miss something here in the whole run process or order of how PHP/Laravel and JavaSCript/jQuery are executed in combination especially regarding variable substitution?
parent.blade.php
<form id="formAjax">
<div>
@foreach($objectsOfTypeA as $objectOfTypeA)
<label>
<input
type='checkbox'
id="{{$objectOfTypeA->id}}"
name="objectOfTypeA[]"
value="{{$objectOfTypeA->id}}">
</label>
@endforeach
</div>
<div>
@foreach($objectsOfTypeB as $objectOfTypeB)
<label>
<input
type='checkbox'
id="{{$objectOfTypeB->id}}"
name="objectOfTypeB[]"
value="{{$objectOfTypeB->id}}">
</label>
@endforeach
</div>
<div>
<div id="radioButtonDiv"></div> <!-- This is the div container whose content shall be replaced by the embedded.blade.php with AJAX. -->
</div>
</form>
ajax-file.js
const formdata = $("#formAjax").serialize();
$.ajax({
type: "POST",
url: "/ajax/radioButtonDiv",
data: { formData: formdata },
success: function (data) {
$("#radioButtonDiv").html(data.htmlSrc);
},
});
web.php
Route::group([
'prefix' => 'ajax'
], function () {
Route::post('/radioButtonDiv', [AjaxController::class, 'getRadioButtonDiv']);
});
AjaxController.php
class AjaxController extends Controller {
public function getRadioButtonDiv(Request $request) {
// Get data for object types A and B from database
return response()->json(['htmlSrc' => view('somefolder/embedded')
->with('arrayOfObjectsTypeA', $arrayOfObjectsTypeA)
->with('arrayOfObjectsTypeB', $arrayOfObjectsTypeB)
->render()]);
}
}
embedded.blade.php
@if(isset($arrayOfObjectsTypeA))
@foreach($arrayOfObjectsTypeA as $objectOfTypeA)
<h3>{{$objectOfTypeA->name}}</h3>
@if(isset($arrayOfObjectsTypeB))
@foreach($arrayOfObjectsTypeB as $objectOfTypeB)
<h4>{{$objectOfTypeB->name}}:</h4>
<div id="{{$objectOfTypeA->name}}-{{$objectOfTypeB->name}}-parent-div">
<div> <!-- This div container is to be copied on add-button click within the parent div to select other variations of parameter values for the same combination of $objectOfTypeA and $objectOfTypeB and $objectOfTypeB->parameters -->
@foreach($objectOfTypeB->parameters as $parameter)
<div>
<h5 class="title">{{$parameter->name}}</h5>
@foreach($parameter->parameterOptions as $option)
<input type="radio"
id="{{$option->name.$option->id}}"
name="parameterOptions[{{"$objectOfTypeA->id"}}-{{$objectOfTypeB->id}}][{{"$parameter->id"}}]"
value="{{$option->id}}"
<label for="{{$option->name}}">{{$option->name}}</label><br>
@endforeach
</div>
@endforeach
</div>
</div>
<button
type='button'
id="{{$objectOfTypeA->name}}-{{$objectOfTypeB->name}}-add-button"
>
Add <!-- Add another div container with radio buttons for the same combination of $objectOfTypeA and $objectOfTypeB and $objectOfTypeB->parameters to chose another variation of parameter values -->
</button>
@endforeach
@endif
@endforeach
@endif
<script>
$("#radioButtonDiv").ready(function() {
var arrayOfObjectsTypeA = @json($arrayOfObjectsTypeA);
var arrayOfObjectsTypeB = @json($arrayOfObjectsTypeB);
for (const objectOfTypeA of arrayOfObjectsTypeA) {
for (const objectOfTypeB of arrayOfObjectsTypeB) {
var prefix = (objectOfTypeA.name + "-" + objectOfTypeB.name).toLowerCase();
$("#" + prefix + "-add-button").on("click", function () {
$(
`<div>
@foreach($objectOfTypeB->parameters as $parameter)
<div>
<h5 class="title">{{$parameter->name}}</h5>
@foreach($parameter->parameterOptions as $option)
<input type="radio"
id="{{$option->name.$option->id}}"
name="parameterOptions[{{"$objectOfTypeA->id"}}-{{$objectOfTypeB->id}}][{{"$parameter->id"}}]"
value="{{$option->id}}"
<label for="{{$option->name}}">{{$option->name}}</label><br>
@endforeach
</div>
@endforeach
</div>`
).appendTo("#" + prefix + "-parent-div");
});
}
}
}
</script>