I have a group of checkboxes representing days of the week. I want to put a maximum and minimum required amount of checkboxes to be selected.
If no checkboxes are selected, I want all the checkboxes to be required. Once at least one checkbox is checked, make required on the rest of the checkboxes false.
Then say if more than 3 checkboxes are selected, disable the remainder of the unchecked boxes.
Here's what I come up with so far. Hopefully I'm not too far off and someone can help me fill in the blanks.
The Function I'm Guessing? {
if (However I say if none are selected) {
$w('#Sunday').required = true;
$w('#Monday').required = true;
$w('#Tuesday').required = true;
$w('#Wednesday').required = true;
$w('#Thursday').required = true;
$w('#Friday').required = true;
$w('#Saturday').required = true;
}
else {
$w('#Sunday').required = false;
$w('#Monday').required = false;
$w('#Tuesday').required = false;
$w('#Wednesday').required = false;
$w('#Thursday').required = false;
$w('#Friday').required = false;
$w('#Saturday').required = false;
}
if (However I say at least one is selected) {
$w('#Sunday').required = false;
$w('#Monday').required = false;
$w('#Tuesday').required = false;
$w('#Wednesday').required = false;
$w('#Thursday').required = false;
$w('#Friday').required = false;
$w('#Saturday').required = false;
}
else {
$w('#Sunday').required = true;
$w('#Monday').required = true;
$w('#Tuesday').required = true;
$w('#Wednesday').required = true;
$w('#Thursday').required = true;
$w('#Friday').required = true;
$w('#Saturday').required = true;
}
if (However I say >3 selected) {
$w('#Sunday').diable();
$w('#Monday').disable();
$w('#Tuesday').disable();
$w('#Wednesday').disable();
$w('#Thursday').disable();
$w('#Friday').disable();
$w('#Saturday').disable();
if ($w('#Sunday').checked) {
$w('#Sunday').enabled();
}
else {
$w('#Sunday').disable();
}
if ($w('#Monday').checked) {
$w('#Monday').enabled();
}
else {
$w('#Monday').disable();
}
if ($w('#Tuesday').checked) {
$w('#Tuesday').enabled();
}
else {
$w('#Tuesday').disable();
}
if ($w('#Wednesday').checked) {
$w('#Wednesday').enabled();
}
else {
$w('#Wednesday').disable();
}
if ($w('#Thursday').checked) {
$w('#Thursday').enabled();
}
else {
$w('#Thursday').disable();
}
if ($w('#Friday').checked) {
$w('#Friday').enabled();
}
else {
$w('#Friday').disable();
}
if ($w('#Saturday').checked) {
$w('#Saturday').enabled();
}
else {
$w('#Saturday').disable();
}
}
else {
$w('#Sunday').enabled();
$w('#Monday').enabled();
$w('#Tuesday').enabled();
$w('#Wednesday').enabled();
$w('#Thursday').enabled();
$w('#Friday').enabled();
$w('#Saturday').enabled();
}
}
You can simply do this by creating an event handler for your element using onChange. For this example, I set my max to 4 options and my element name is 'coachingPriorities'. You will need to change the code below to your elements names:
let selected = [] let coachingPrioritesSelectionTags export function coachingPriorites_change(event) { //limit to 4 selection max let value = event.target.value let length = value.length console.log(length, 'coaching priority tags length') for (var i = 0; i < length - 1; i++) { if (length <= 4) { selected = value } else { value = selected } } console.log(value, 'coaching tags value') coachingPrioritesSelectionTags = value console.log(coachingPrioritesSelectionTags, 'coaching tag string value') setTimeout(() => { $w('#coachingPriorites').value = [] $w('#coachingPriorites').value = value }, 1) }
I really enjoyed this post. (And now I want some beer) ..... LOL ..... ;)
Cheers! 🍻
Thanks Yisreal! lol that makes a lot more sense. This explains a lot, I've tried to declare variables outside of functions and I was wondering why they weren't working the way I thought they would. THIS is why. lol
Thanks Again! I'm excited to rewrite a lot of code to work this way. 😁
Hey YoYo,
Wow! I had a major be-dumb moment. Sorry. I guess I owe you a beer.🍻
Here's the code again, this time with the correction (I also corrected my original post):
export function checkbox_change(event) { //Add your code for this event here: console.log(event); // get the number of checkboxes that are checked //var number = $w("#lager").checked + $w("#stout").checked + $w("#pilsner").checked + $w("#ipa").checked; var number = num_checked(); console.log("num: " + number); if(number > 2) { console.log("more than two checked"); } else if(number == 0) { console.log("none are checked"); } else { console.log("two or fewer are checked"); } } function num_checked() { var number = $w("#lager").checked + $w("#stout").checked + $w("#pilsner").checked + $w("#ipa").checked; return number; }
I commented out the original line of code that gets the number of checkboxes that are checked, and I replaced it with the call to the subroutine that does the same thing. The idea is that you can call the subroutine as many times as you want whereever you need. This is a trivial example, but a subroutine that has a more complex calculation can save you a lot of code, and make the program easier to read and maintain.
I'm a little confused, I don't see where/how num_checked() is being called upon within the checkbox_change().
Simply put, a subroutine is just a routine, but the idea is to create reusable code.
Here's my original example, but using a subroutine to return the number of checkboxes that are checked:
export function checkbox_change(event) { //Add your code for this event here: console.log(event); // get the number of checkboxes that are checked //var number = $w("#lager").checked + $w("#stout").checked + $w("#pilsner").checked + $w("#ipa").checked; var number = num_checked(); console.log("num: " + number); if(number > 2) { console.log("more than two checked"); } else if(number == 0) { console.log("none are checked"); } else { console.log("two or fewer are checked"); } } function num_checked() { var number = $w("#lager").checked + $w("#stout").checked + $w("#pilsner").checked + $w("#ipa").checked; return number; }
The routine (or subroutine) num_checked() is called in the checkbox_change() routine and returns the number of checkboxes that are checked. You can then call num_checked() whenever you need to find out how many checkboxes have been checked.
The advantages of using subroutines:
you can easily reuse tested code without having to copy/paste
if you need to change the code, you only need to change in one place
makes your code easier to read since it is more modular and better organized
This should get you started with the idea of subroutines and reusable code. A search for Javascript subroutines will give you plenty of reading material.
O_O yep, that is beyond my skills at the moment... what's a subroutine? haha I haven't found any helpful articles on how to make them or make them work.
I did manage to get part of my goals achieved. For each checkbox I've added this code (in bold) to the existing onChange Functions. And it works! Below the code is the last thing I'm trying to figure out.
export function admDaySun1_change() { let SunAdmDet = $w("#admDetailsSun1"); let SunAdmLen = $w("#admLengthSun1"); let SunAdmSta = $w("#admStartSun1"); let SunAdm = $w("#admDaySun1"); let MonAdm = $w("#admDayMon1"); let TueAdm = $w("#admDayTue1"); let WedAdm = $w("#admDayWed1"); let ThurAdm = $w("#admDayThur1"); let FriAdm = $w("#admDayFri1"); let SatAdm = $w("#admDaySat1"); var isChecked = SunAdm.checked + MonAdm.checked + TueAdm.checked + WedAdm.checked + ThurAdm.checked + FriAdm.checked + SatAdm.checked; if (isChecked !== 0) { console.log('At Least 1 Selected'); SunAdm.required = false; MonAdm.required = false; TueAdm.required = false; WedAdm.required = false; ThurAdm.required = false; FriAdm.required = false; SatAdm.required = false; } else { console.log('None Selected'); SunAdm.required = true; MonAdm.required = true; TueAdm.required = true; WedAdm.required = true; ThurAdm.required = true; FriAdm.required = true; SatAdm.required = true; } if( SunAdm.checked) { SunAdmDet.expand(); SunAdmLen.required = true; SunAdmSta.required = true; console.log('Expanding Sun Adm Details 1 \& Requiring Sun Length and Start Time'); } else { SunAdmDet.collapse(); SunAdmLen.required = false; SunAdmSta.required = false; } }
Now my only issue is, is that I can't figure out how to disable the unchecked boxes once a specific number of boxes are checked, leaving the checked boxes enabled. Then re-enabling the previously disabled checkboxes if a checked box is unselected.
I've also updated the Github file with the newest code.
Create a subroutine containing the code, and then call it from each of the other onChange() functions.
There are of course a myriad of solutions possible, with mine just one possibility - and not necessarily even highly recommended.
I would suggest that you first identify the required functionality, and then structure the logic so that it is easily understood and maintainable.
I'm not sure if this will help but I've copied my entire page code (so far) to a github file if you'd like to see what has been done in full. https://github.com/YoYo-Trigger/Wix-Code/blob/master/inProgress-VolunteerApplication
Oh wow, that's awesome, thank you so much for the thorough explanation! It's going to take a bit to process it all. lol
I have a small problem, for this step you gave me.
I already have the onChange functions connected to this block of code.
// FOR ADMINS | Start export function admDaySun1_change() { let SunAdm = $w("#admDaySun1"); let SunAdmDet = $w("#admDetailsSun1"); let SunAdmLen = $w("#admDetailsSun1"); let SunAdmSta = $w("#admStartSun1"); if( SunAdm.checked) { SunAdmDet.expand(); SunAdmLen.required = true; SunAdmSta.required = true; console.log('Expanding Sun Adm Details 1 \& Requiring Sun Length and Start Time'); } else { SunAdmDet.collapse(); SunAdmLen.required = false; SunAdmSta.required = false; } } export function admDayMon1_change() { let MonAdm = $w("#admDayMon1"); let MonAdmDet = $w("#admDetailsMon1"); let MonAdmLen = $w("#admLengthMon1"); let MonAdmSta = $w("#admStartMon1"); if(MonAdm.checked) { MonAdmDet.expand(); MonAdmLen.required = true; MonAdmSta.required = true; console.log('Expanding Mon Adm Details 1 \& Requiring Mon Length and Start Time'); } else { MonAdmDet.collapse(); MonAdmLen.required = false; MonAdmSta.required = false; } } export function admDayTue1_change() { let TueAdm = $w("#admDayTue1"); let TueAdmDet = $w("#admDetailsTue1"); let TueAdmLen = $w("#admLengthTue1"); let TueAdmSta = $w("#admStartTue1"); if(TueAdm.checked) { TueAdmDet.expand(); TueAdmLen.required = true; TueAdmSta.required = true; console.log('Expanding Tue Adm Details 1 \& Requiring Tue Length and Start Time'); } else { TueAdmDet.collapse(); TueAdmLen.required = false; TueAdmSta.required = false; } } export function admDayWed1_change() { let WedAdm = $w("#admDayWed1"); let WedAdmDet = $w("#admDetailsWed1"); let WedAdmLen = $w("#admLengthWed1"); let WedAdmSta = $w("#admStartWed1"); if(WedAdm.checked) { WedAdmDet.expand(); WedAdmLen.required = true; WedAdmSta.required = true; console.log('Expanding Wed Adm Details 1 \& Requiring Wed Length and Start Time'); } else { WedAdmDet.collapse(); WedAdmLen.required = false; WedAdmSta.required = false; } } export function admDayThur1_change() { let ThurAdm = $w("#admDayThur1"); let ThurAdmDet = $w("#admDetailsThur1"); let ThurAdmLen = $w("#admLengthThur1"); let ThurAdmSta = $w("#admStartThur1"); if(ThurAdm.checked) { ThurAdmDet.expand(); ThurAdmLen.required = true; ThurAdmSta.required = true; console.log('Expanding Thur Adm Details 1 \& Requiring Thur Length and Start Time'); } else { ThurAdmDet.collapse(); ThurAdmLen.required = false; ThurAdmSta.required = false; } } export function admDayFri1_change() { let FriAdm = $w("#admDayFri1"); let FriAdmDet = $w("#admDetailsFri1"); let FriAdmLen = $w("#admLengthFri1"); let FriAdmSta = $w("#admStartFri1"); if(FriAdm.checked) { FriAdmDet.expand(); FriAdmLen.required = true; FriAdmSta.required = true; console.log('Expanding Fri Adm Details 1 \& Requiring Fri Length and Start Time'); } else { FriAdmDet.collapse(); FriAdmLen.required = false; FriAdmSta.required = false; } } export function admDaySat1_change() { let SatAdm = $w("#admDaySat1"); let SatAdmDet = $w("#admDetailsSat1"); let SatAdmLen = $w("#admLengthSat1"); let SatAdmSta = $w("#admStartSat1"); if(SatAdm.checked) { SatAdmDet.expand(); SatAdmLen.required = true; SatAdmSta.required = true; console.log('Expanding Sat Adm Details 1 \& Requiring Sat Length and Start Time'); } else { SatAdmDet.collapse(); SatAdmLen.required = false; SatAdmSta.required = false; } } // FOR ADMINS | End
This code expands a group of two dropdowns per checked box and makes them required. If unchecked, collapses the group and removes the requirements on the dropdowns. How would I go about adding the new code without messing up this code? Since each checkbox has already been assigned an individual onChange() function, I don't know how to approach this.
Hi again YoYo, You can't really nest an else inside an if, since an else is an optional “other” to an if - that is, the else optionally accompanies the if. You can however, nest an if, or even an if/else inside of another if or an else. Let’s take it a step at a time and try to make sense of it... Let’s take this compelling piece of code and see what happens when a certain condition is met:
var condition = true; var a = 1; console.log("before: " + a); if (condition === true) { a = a + 1; } // notice that there is no else here console.log("after: " + a); // a is now equal to 2
Run the above code and you will see the following in the Developers console:
before: 1 after: 2
Oftentimes, we want to be able to perform different actions: one when the condition is true and another when the condition is false.
var condition = // first run with true, and then run with false var a = 1; console.log("before: " + a); if (condition === true) { a = a + 1; } else { a = a - 1; } console.log("after: " + a);
Run with condition = true and we get the following results:
before: 1 after: 2
However, if we run the code with condition = false, we get:
before: 1 after: 0
As you can see, we have two different conditions, with two different results. Now let’s use nesting to handle a more complex problem…
var drink; var rainy = false; var temperature = 11; if (rainy === true) { if(temperature < 10) { drink = "cough medicine"; } else { drink = "hot chocolate"; } } else { // not rainy if(temperature < 28) { drink = "beer"; } else { drink = "several beers"; } } console.log("drink: " + drink);
The above code example checks for two different conditions and takes the appropriate action based on both conditions. Try running the example with rainy = true and rainy = false, while also trying various temperatures. You will see the results in the Developers console. Sometimes conditions call for a beer, sometimes you’ll need hot chocolate, and so on. You can add additional conditions and nest even deeper if needed. You can use a simple if, or an if with an accompanying else.
Another way to use if/else would be to handle a series of conditions:
var a = 1; var b; if(a === 0) { b = "0"; } else if (a === 1) { b = "1"; } else if (a === 2) { b = "2"; } else if (a === 3) { b = "3"; } else { b = "error"; } console.log(b);
Just for fun (didn't you just love it when your teachers would say that?), do a search for the Javascript switch statement for a perhaps simpler, or more direct, way to write the above if/else chain. Try it yourself and come back to me if you need help.
Have fun,
Yisrael
Thank you so much Yisrael. I can't wait to give this a shot. I just learned about else if statements last night on codecademy and I thought I may have to incorporate them for this. I'm pretty sure you're heading me in the right direction.
As for what I'm trying to do, hopefully I can explain it a little better;
I am creating an application form for multiple volunteer positions. I have it set up so that each position has it's own container and when selected from a radio button group it expands the relevant container.
Each container has 7 checkboxes, each for a day of the week and currently I have the onChange() function for each checkbox expanding a group consisting of two dropdowns per checkbox.
I want for each position container, that is expanded, the applicant to be required to select at least one of the checkboxes. Then also set a maximum amount of checkboxes that can be selected, by disabling the remaining unchecked boxes. Leaving the checked boxes enabled so that if the applicant makes a mistake they can uncheck the box, which in turn, re-enables the previously disabled checkboxes.
I hope this explains what I'm trying to do more thoroughly. Let me know if anything is unclear.
Thanks Again!
YoYo xx
P.S. I can't find the answer to this anywhere, maybe you know the answer.
Can you nest an else statment in an else if statement?
I.E.
if { if { else if { else { } } } else { } } else { }
Hey YoYo,
How are you? I'm not exactly sure what you are trying to accomplish, but let me take a stab at it with some example code.
I created a page with 4 checkboxes with these IDs: #lager, #stout, #pilsner, #ipa - four different types of beer.
For each checkbox, I set the onChange() routine to point to the same callback routine: checkbox_change().
The code for the onChange() routine is:
export function checkbox_change(event) { //Add your code for this event here: console.log(event); // get the number of checkboxes that are checked var number = $w("#lager").checked + $w("#stout").checked + $w("#pilsner").checked + $w("#ipa").checked; console.log("num: " + number); if(number > 2) { console.log("more than two checked"); } else if(number == 0) { console.log("none are checked"); } else { console.log("two or fewer are checked"); } }
I use console.log() all the time to let me know what's going on with the code - console.log() is your friend. The first thing I do in the checkbox_change() routine is to display the event details in the WixCode developer console. This will show what checkbox was changed (checked or unchecked) and provides some context.
Then I get the number of checkboxes that are checked. For example, $w("#lager").checked returns a boolean value. A boolean value is true or false, but it conveniently is also 1 or 0. We add up all of the returned values to give us the number of checkboxes that are checked. Then we can use the number of checked checkboxes to take some action. In my example I merely displayed the result using console.log().
Hopefully this helps. Let me know if I'm going in the right direction.
All the best,
Yisrael
So tonight I came up with this, it does the exact same thing as I did yesterday. Requires all the checkboxes but does remove the requirements once one is checked.
I'm going in circles here. Some help would be GREATLY appreciated. xx
var Days1 = ["#admDaySun1", "#admDayMon1", "#admDayTue1", "#admDayWed1", "#admDayThur1", "#admDayFri1", "#admDaySat1"]; var Sun1 = Days1[0]; var Mon1 = Days1[1]; var Tue1 = Days1[2]; var Wed1 = Days1[3]; var Thur1 = Days1[4]; var Fri1 = Days1[5]; var Sat1 = Days1[6]; if ($w('Days1:checkbox:checked').length <=0) { $w(Sun1).required = true; $w(Mon1).required = true; $w(Tue1).required = true; $w(Wed1).required = true; $w(Thur1).required = true; $w(Fri1).required = true; $w(Sat1).required = true; } else { $w(Sun1).required = false; $w(Mon1).required = false; $w(Tue1).required = false; $w(Wed1).required = false; $w(Thur1).required = false; $w(Fri1).required = false; $w(Sat1).required = false; }
I halfway figured out the If None Are Selected part
So this code, makes them all required if none are selected but does not remove the requirements from the rest of the checkboxes. Also I'm pretty sure this will still make them required even if the container their in is collapsed but I'm confused on where to start on that.
if ($w('#admDiv1:checked').length <= 0) { $w('#admDaySun1').required = true; $w('#admDayMon1').required = true; $w('#admDayTue1').required = true; $w('#admDayWed1').required = true; $w('#admDayThur1').required = true; $w('#admDayFri1').required = true; $w('#admDaySat1').required = true; } else { $w('#admDaySun1').required = false; $w('#admDayMon1').required = false; $w('#admDayTue1').required = false; $w('#admDayWed1').required = false; $w('#admDayThur1').required = false; $w('#admDayFri1').required = false; $w('#admDaySat1').required = false; }
Also I was too lazy to bother to simplify code. It's bedtime and I have to give up for the night, or I'll be up 'til dawn. 😅