I have two radio
button groups:
- For
attendance
and have values of "yes" and "no" - For
dietary
choice and has the values of "Vegetarian / Vegan" and "Non-vegetarian"
The fields for dietary
only show if the user has selected "yes" for attendance.
I’m sorting those who have accepted, declined, chose veg or non-veg into their own arrays (so 4 arrays exist). The values for these 4 arrays are passed onto a hidden field which is then posted to DB.
I have successfully managed to sort who has accepted or declined into their own arrays. However, since I’ve added another change
function to sort the diet options also, I get mixed results. Steps to recreate in the demo:
- For "John", click yes for attendance
- John is added to the
attending list
(console log) - For "John", click "Non-vegetarian"
- John is added to the
non veg list
- For Alex, click yes for attendance
- Alex is added to the
attending list
alongside John - For Alex, click "Vegetarian / Vegan"
- Alex is added to the "veg list", but John is removed from the "Non veg list"
Also, if a user clicks yes to attendance initially, then selects a diet option and then clicks "no" to attendance after, their name from the diet arrays should be removed (since they’re not attending). I’ve tried to address this with if ( attendance_radio.val() == "yes" ) { }
but no luck.
Demo below:
(function ($) {
var attendance_radio = $(".input-radio-attendance");
var diet_radio = $(".input-radio-diet");
var accepted_array = [];
var declined_array = [];
var veg_array = [];
var nonveg_array = [];
/* sort accepted and declined into arrays */
attendance_radio.on('change', function() {
var $this = $(this);
var name = $this.data("name");
var checkedVal = $this.val();
if (checkedVal == "yes") {
accepted_array.push(name);
declined_array.splice($.inArray(name, declined_array), 1);
}
else {
declined_array.push(name);
accepted_array.splice($.inArray(name, accepted_array), 1);
}
var accepted_list = accepted_array.join(",");
var declined_list = declined_array.join(",");
console.log("attending list: " + accepted_list);
console.log("declined list: " + declined_list);
});
/* get count of veg and non veg numbers */
diet_radio.on('change', function() {
var $this = $(this);
var name = $this.data("name");
var checkedVal = $this.val();
// only add to array if user is attending
if ( attendance_radio.val() == "yes" ) {
if (checkedVal == "veg") {
veg_array.push(name);
nonveg_array.splice($.inArray(name, nonveg_array), 1);
}
else {
nonveg_array.push(name);
veg_array.splice($.inArray(name, veg_array), 1);
}
}
var veg_list = veg_array.join(",");
var nonveg_list = nonveg_array.join(",");
console.log("veg list: " + veg_list);
console.log("non veg list: " + nonveg_list);
});
/* showing dietary fields if yes is selected */
attendance_radio.each(function(index) {
$(this).on("click", function() {
var $this = $(this);
var checkedVal = $this.val();
if( checkedVal == "yes" ) {
$this.closest(".guest").find(".dietary").addClass("d-flex");
diet_radio.prop('required',true);
}
else {
$this.closest(".guest").find(".dietary").removeClass("d-flex");
diet_radio.prop('required',false);
}
});
});
}) (jQuery);
.group,
.group__inner{
display: flex;
}
.group{
width: 50%;
padding: 30px;
flex-direction: column;
}
span{
display: block;
margin-bottom: 20px;
}
.dietary{
display: none;
}
.attendance{
display: flex;
}
.d-flex{
display: flex;
}
.as-console-wrapper {
left: auto!important;
width: 50%;
min-height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div class="group">
<!------------->
<!-- guest 1 -->
<!------------->
<div class="guest">
<span class="guest__name">John</span>
<div class="guest__options">
<!-- attendace -->
<div class="attendance">
<span>Attending?</span>
<div class="group__inner">
<div class="guest__options-group">
<input class="input-radio-attendance" id="attending-yes-0" type="radio" name="attendance-0" value="yes" data-name="John" required />
<label for="attending-yes-0">Yes</label>
</div>
<div class="guest__options-group">
<input class="input-radio-attendance" id="attending-no-0" type="radio" name="attendance-0" value="no" data-name="John" required />
<label for="attending-no-0">No</label>
</div>
</div>
</div>
<!-- show dietary options when attendace is yes -->
<div class="dietary">
<span>Dietary preference</span>
<div class="group__inner">
<div class="guest__options-group">
<input class="input-radio-diet" id="diet-veg-0" type="radio" name="diet-0" value="veg" data-name="John" required />
<label for="diet-veg-0">Vegetarian / Vegan</label>
</div>
<div class="guest__options-group">
<input class="input-radio-diet" id="diet-nonveg-0" type="radio" name="diet-0" value="nonveg" data-name="John" required />
<label for="diet-nonveg-0">Non-vegetarian</label>
</div>
</div>
</div>
</div>
</div>
<!------------->
<!-- guest 2 -->
<!------------->
<div class="guest">
<span class="guest__name">Alex</span>
<div class="guest__options">
<!-- attendace -->
<div class="attendance">
<span>Attending?</span>
<div class="group__inner">
<div class="guest__options-group">
<input class="input-radio-attendance" id="attending-yes-1" type="radio" name="attendance-1" value="yes" data-name="Alex" required />
<label for="attending-yes-0">Yes</label>
</div>
<div class="guest__options-group">
<input class="input-radio-attendance" id="attending-no-1" type="radio" name="attendance-1" value="no" data-name="Alex" required />
<label for="attending-no-1">No</label>
</div>
</div>
</div>
<!-- show dietary options when attendace is yes -->
<div class="dietary">
<span>Dietary preference</span>
<div class="group__inner">
<div class="guest__options-group">
<input class="input-radio-diet" id="diet-veg-1" type="radio" name="diet-1" value="veg" data-name="Alex" required />
<label for="diet-veg-1">Vegetarian / Vegan</label>
</div>
<div class="guest__options-group">
<input class="input-radio-diet" id="diet-nonveg-1" type="radio" name="diet-1" value="nonveg" data-name="Alex" required />
<label for="diet-nonveg-1">Non-vegetarian</label>
</div>
</div>
</div>
</div>
</div>
</div>
Also tried
diet_radio.on('change', function() {
var $this = $(this);
var name = $this.data("name");
var checkedVal = $this.val();
// only add to diet arrays if user is attending
if ( $(this).closest(".guest").find(".input-radio-attendance:checked").val() == "yes" ) {
if (checkedVal == "veg") {
veg_array.push(name);
nonveg_array.splice($.inArray(name, nonveg_array), 1);
} else {
nonveg_array.push(name);
veg_array.splice($.inArray(name, veg_array), 1);
}
}
// if user selects yes to attendance, then selects a diet option, then changes atendance to no, remove them from diet arrays
if( accepted_list.includes(name) ){
veg_array.splice( $.inArray(name, veg_array), 1 );
nonveg_array.splice( $.inArray(name, nonveg_array), 1 );
}
var veg_list = veg_array.join(",");
var nonveg_list = nonveg_array.join(",");
veg_field.val(veg_list);
nonveg_field.val(nonveg_list);
console.log("veg list: " + veg_list);
console.log("non veg list: " + nonveg_list);
});
Edit @Lajos Arpad
Edit 2 @Lajos Arpad
Still seeing a bug where user isn’t removed from list after declining when initially choosing there diet option.
For ease, I’ve created this demo, which contains your latest solution to date. I’ve just added fields so we can see the list values on the page, rather than via console logs.
(function($) {
var attendance_radio = $(".input-radio-attendance");
var diet_radio = $(".input-radio-diet");
var accepted_array = [];
var declined_array = [];
var veg_array = [];
var nonveg_array = [];
/* sort accepted and declined into arrays */
attendance_radio.on('change', function() {
if (this.value === 'no') {
$(".input-radio-diet[data-name='" + $(this).data("name") + "']").prop('checked', false);
}
var $this = $(this);
var name = $this.data("name");
var checkedVal = $this.val();
if (checkedVal == "yes") {
accepted_array.push(name);
let index = declined_array.indexOf(name);
if (index >= 0) {
declined_array.splice(index, 1);
}
} else {
declined_array.push(name);
let index = 0;
for (let theArray of [accepted_array, nonveg_array, veg_array]) {
let index = theArray.indexOf(name);
if (index >= 0) {
theArray.splice(index, 1);
}
}
}
var accepted_list = accepted_array.sort().join(",");
var declined_list = declined_array.sort().join(",");
$("#attending-list p").text(accepted_list);
$("#declined-list p").text(declined_list);
/* console.log("attending list: " + accepted_list);
console.log("declined list: " + declined_list); */
});
/* get count of veg and non veg numbers */
diet_radio.on('change', function() {
var $this = $(this);
var name = $this.data("name");
var checkedVal = $this.val();
// only add to array if user is attending
if (attendance_radio.val() == "yes") {
if (checkedVal == "veg") {
veg_array.push(name);
let index = nonveg_array.indexOf(name);
if (index >= 0) {
nonveg_array.splice(index, 1);
}
} else {
nonveg_array.push(name);
let index = veg_array.indexOf(name);
if (index >= 0) {
veg_array.splice(index, 1);
}
}
}
var veg_list = veg_array.sort().join(",");
var nonveg_list = nonveg_array.sort().join(",");
$("#veg-list p").text(veg_list);
$("#nonveg-list p").text(nonveg_list);
/* console.log("veg list: " + veg_list);
console.log("non veg list: " + nonveg_list); */
});
/* showing dietary fields if yes is selected */
attendance_radio.each(function(index) {
$(this).on("click", function() {
var $this = $(this);
var checkedVal = $this.val();
if (checkedVal == "yes") {
$this.closest(".guest").find(".dietary").addClass("d-flex");
diet_radio.prop('required', true);
} else {
$this.closest(".guest").find(".dietary").removeClass("d-flex");
diet_radio.prop('required', false);
}
});
});
})(jQuery);
.group,
.group__inner {
display: flex;
}
.group {
padding: 30px;
flex-direction: column;
}
span {
display: block;
margin-bottom: 20px;
}
.dietary {
display: none;
}
.attendance {
display: flex;
}
.d-flex {
display: flex;
}
/* results */
.results {
margin-top: 30px;
background: lightblue;
padding: 20px;
}
.results p {
margin: 0;
}
.results span {
display: flex;
align-items: center;
margin-bottom: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div class="group">
<!------------->
<!-- guest 1 -->
<!------------->
<div class="guest">
<span class="guest__name">John</span>
<div class="guest__options">
<!-- attendace -->
<div class="attendance">
<span>Attending?</span>
<div class="group__inner">
<div class="guest__options-group">
<input class="input-radio-attendance" id="attending-yes-0" type="radio" name="attendance-0" value="yes" data-name="John" required />
<label for="attending-yes-0">Yes</label>
</div>
<div class="guest__options-group">
<input class="input-radio-attendance" id="attending-no-0" type="radio" name="attendance-0" value="no" data-name="John" required />
<label for="attending-no-0">No</label>
</div>
</div>
</div>
<!-- show dietary options when attendace is yes -->
<div class="dietary">
<span>Dietary preference</span>
<div class="group__inner">
<div class="guest__options-group">
<input class="input-radio-diet" id="diet-veg-0" type="radio" name="diet-0" value="veg" data-name="John" required />
<label for="diet-veg-0">Vegetarian / Vegan</label>
</div>
<div class="guest__options-group">
<input class="input-radio-diet" id="diet-nonveg-0" type="radio" name="diet-0" value="nonveg" data-name="John" required />
<label for="diet-nonveg-0">Non-vegetarian</label>
</div>
</div>
</div>
</div>
</div>
<!------------->
<!-- guest 2 -->
<!------------->
<div class="guest">
<span class="guest__name">Alex</span>
<div class="guest__options">
<!-- attendace -->
<div class="attendance">
<span>Attending?</span>
<div class="group__inner">
<div class="guest__options-group">
<input class="input-radio-attendance" id="attending-yes-1" type="radio" name="attendance-1" value="yes" data-name="Alex" required />
<label for="attending-yes-0">Yes</label>
</div>
<div class="guest__options-group">
<input class="input-radio-attendance" id="attending-no-1" type="radio" name="attendance-1" value="no" data-name="Alex" required />
<label for="attending-no-1">No</label>
</div>
</div>
</div>
<!-- show dietary options when attendace is yes -->
<div class="dietary">
<span>Dietary preference</span>
<div class="group__inner">
<div class="guest__options-group">
<input class="input-radio-diet" id="diet-veg-1" type="radio" name="diet-1" value="veg" data-name="Alex" required />
<label for="diet-veg-1">Vegetarian / Vegan</label>
</div>
<div class="guest__options-group">
<input class="input-radio-diet" id="diet-nonveg-1" type="radio" name="diet-1" value="nonveg" data-name="Alex" required />
<label for="diet-nonveg-1">Non-vegetarian</label>
</div>
</div>
</div>
</div>
</div>
<!-- see values -->
<div class="results">
<span id="attending-list"><strong>Attending: </strong>
<p></p>
</span>
<span id="declined-list"><strong>Declined: </strong>
<p></p>
</span>
<span id="veg-list"><strong>Veg: </strong>
<p></p>
</span>
<span id="nonveg-list"><strong>Non veg: </strong>
<p></p>
</span>
</div>
</div>
In the above demo, perform the following steps to recreate the issue:
- For "John", click "yes" for attendance
- ["John" is added to the "Attending" list]
- For "John", click "Vegetarian / Vegan" for diet
- ["John" is added to the "Veg" list]
- For "Alex", click "yes" for attendance
- ["John" and "Alex" now exist in the "Attending" list]
- For "Alex", click "Non-vegetarian" for for diet
- ["Alex" is added to the "Non-veg" list]
- (Currently we have
attending
: "Alex, John",declined
: "",veg
: John andnon-veg
: "Alex") - Now, for "John", change his attendance to "no" but "John" still exists in the
veg
list
2
Answers
You can simply
sort()
your arrays before joining them:EDIT: Applied two fixes:
EDIT
Added additional logging for veg/nonveg after not attending. Sample test:
First check if element exist in array before splicing else splice with start from -1 index element i.e. last element and it will empty array in your case
For Second Point You need to add item removal code when user unselect the attendance
For more information read out