I have a simple php 'foreach' loop which works fine when there is only one loop. The php code displays a simple select box which shows or hides a div based on the selection value. The select box and div's are then repeated within each loop. The problem is that when there is more than one repeat of the code in the loop, the show/hide JavaScript does not work as the ID's are not unique, only the first in the loop works.
How can I get this to work within a loop? Does the ID need to be unique or is there a better way to do this with Javascript?
PHP CODE:
foreach ( $order->get_items() as $item_id => $item ) {
echo 'Service Area:';
echo '<select id="serviceareaselect">';
echo '<option value="servicearea">Select an Area...</option>';
echo '<option value="area1">Area 1</option>';
echo '<option value="area2">Area 2</option>';
echo '</select>';
// Service Area 1
echo '<div id="area1" style="display:none">';
echo '<input type="checkbox" id="dur1" name="dur1" value="Dur1"><label for="vehicle1">Dur1</label><br>';
echo '<input type="checkbox" id="dur2" name="dur2" value="Dur2"><label for="vehicle1">Dur2</label><br>';
echo '</div>';
// Service Area 2
echo '<div id="area2" style="display:none">';
echo '<input type="checkbox" id="aln1" name="aln1" value="Aln1"><label for="vehicle1">Aln1</label><br>';
echo '<input type="checkbox" id="aln2" name="aln2" value="Aln2"><label for="vehicle1">Aln2</label><br>';
echo '</div>';
}
JAVASCRIPT CODE:
$(function()
{
$("#serviceareaselect").change(function(){
$(".servicearea").hide();
$("#" $(this).val()).show();
});
});
CodePudding user response:
Using no ID attributes at all it is easy to identify which items to process by inspecting the event
and especially event.target
If you assign a delegated event listener
to some ancestor element ( in this case I used the document itself ) thanks to event bubbling you are able to identify which particular DOM node triggered the change
event and from that, using other selector mechanisms (querySelector, querySelectorAll, parentNode etc ) it is trivial to manipulate other DOM elements as appropriate.
The example below is slightly modified in that the HTML portion that you were rendering in PHP now have common parent elements to make the task of identification easier.
Regardless of how many such elements section
items were to be rendered the event handler mechanism should work the same with no need to add integers to ID attributes which, quite honestly, gets messy.
The Javascript is vanilla Javascript as I don't use jQuery and would likely mislead with my attempts at using it but no doubt there are appropriate jQuery methods available to do this.
document.addEventListener('change', e => {
if (e.target.name == 'serviceareaselect') {
let parent = e.target.parentNode;
parent.querySelectorAll('.servicearea').forEach(n => n.style.display = 'none');
if (e.target.options.selectedIndex > 0) parent.querySelector(`[data-id="${e.target.value}"]`).style.display = 'block';
}
})
label{display:block}
<section>
Service Area:
<select name="serviceareaselect">
<option value="servicearea">Select an Area...
<option value="area1">Area 1
<option value="area2">Area 2
</select>
// Service Area 1
<div data-id="area1" style="display:none">
<label><input type="checkbox" name="dur1" value="Dur1">Dur1</label>
<label><input type="checkbox" name="dur2" value="Dur2">Dur2</label>
</div>
// Service Area 2
<div data-id="area2" style="display:none">
<label><input type="checkbox" name="aln1" value="Aln1">Aln1</label>
<label><input type="checkbox" name="aln2" value="Aln2">Aln2</label>
</div>
</section>
<section>
Service Area:
<select name="serviceareaselect">
<option value="servicearea">Select an Area...
<option value="area1">Area 1
<option value="area2">Area 2
</select>
// Service Area 1
<div data-id="area1" style="display:none">
<label><input type="checkbox" name="dur1" value="Dur1">Dur1</label>
<label><input type="checkbox" name="dur2" value="Dur2">Dur2</label>
</div>
// Service Area 2
<div data-id="area2" style="display:none">
<label><input type="checkbox" name="aln1" value="Aln1">Aln1</label>
<label><input type="checkbox" name="aln2" value="Aln2">Aln2</label>
</div>
</section>
CodePudding user response:
The Id has to be unique. You can use $item_id
in the loop to make it unique.
PHP code:
foreach ( $order->get_items() as $item_id => $item ) {
echo 'Service Area:';
echo '<select id="serviceareaselect_'.$item_id.'" data-itemid="'.$item_id.'">';
echo '<option value="servicearea">Select an Area...</option>';
echo '<option value="area1_'.$item_id.'">Area 1</option>';
echo '<option value="area2_'.$item_id.'">Area 2</option>';
echo '</select>';
// Service Area 1
echo '<div id="area1_'.$item_id.'" style="display:none">';
echo '<input type="checkbox" id="dur1" name="dur1" value="Dur1"><label for="vehicle1">Dur1</label><br>';
echo '<input type="checkbox" id="dur2" name="dur2" value="Dur2"><label for="vehicle1">Dur2</label><br>';
echo '</div>';
// Service Area 2
echo '<div id="area2_'.$item_id.'" style="display:none">';
echo '<input type="checkbox" id="aln1" name="aln1" value="Aln1"><label for="vehicle1">Aln1</label><br>';
echo '<input type="checkbox" id="aln2" name="aln2" value="Aln2"><label for="vehicle1">Aln2</label><br>';
echo '</div>';
}
JS code:
$(function(){
$(".serviceareaselect").change(function(){
let item_id = $(this).data("itemid");
$(".servicearea_" item_id).hide();
$("#" $(this).val()).show();
});
});