Dynamic limit of Checkbox Group selection
I have a checkboxGroupInput
with 4 choices (A, B, C, D).
I want to limit the allowed selection to 2 options.
The user is allowed to select a 3rd option.
But in that case only the new (3rd) and last (2nd) options that were selected should stay checked.
For example, if a user selects B, then D, and then A -
the outcome should be only D and A checked.
I'm trying to implement this logic in JS, since it doesn't work properly in R/Shiny.
The main reason is that updating the input doesn't occur immediately.
(it is delayed by other invalidations in my original Shiny app, that take quite some time)
Minimal example:
library(shiny)
shinyApp(
ui = fluidPage(
tags$script(
"JS code here..."
),
checkboxGroupInput(
inputId = "the_checkbox",
label = "Checkbox",
choices = c("A", "B", "C", "D")
)
),
server = function(input, output, session) {}
)
javascript jquery r checkbox shiny
add a comment |
I have a checkboxGroupInput
with 4 choices (A, B, C, D).
I want to limit the allowed selection to 2 options.
The user is allowed to select a 3rd option.
But in that case only the new (3rd) and last (2nd) options that were selected should stay checked.
For example, if a user selects B, then D, and then A -
the outcome should be only D and A checked.
I'm trying to implement this logic in JS, since it doesn't work properly in R/Shiny.
The main reason is that updating the input doesn't occur immediately.
(it is delayed by other invalidations in my original Shiny app, that take quite some time)
Minimal example:
library(shiny)
shinyApp(
ui = fluidPage(
tags$script(
"JS code here..."
),
checkboxGroupInput(
inputId = "the_checkbox",
label = "Checkbox",
choices = c("A", "B", "C", "D")
)
),
server = function(input, output, session) {}
)
javascript jquery r checkbox shiny
add a comment |
I have a checkboxGroupInput
with 4 choices (A, B, C, D).
I want to limit the allowed selection to 2 options.
The user is allowed to select a 3rd option.
But in that case only the new (3rd) and last (2nd) options that were selected should stay checked.
For example, if a user selects B, then D, and then A -
the outcome should be only D and A checked.
I'm trying to implement this logic in JS, since it doesn't work properly in R/Shiny.
The main reason is that updating the input doesn't occur immediately.
(it is delayed by other invalidations in my original Shiny app, that take quite some time)
Minimal example:
library(shiny)
shinyApp(
ui = fluidPage(
tags$script(
"JS code here..."
),
checkboxGroupInput(
inputId = "the_checkbox",
label = "Checkbox",
choices = c("A", "B", "C", "D")
)
),
server = function(input, output, session) {}
)
javascript jquery r checkbox shiny
I have a checkboxGroupInput
with 4 choices (A, B, C, D).
I want to limit the allowed selection to 2 options.
The user is allowed to select a 3rd option.
But in that case only the new (3rd) and last (2nd) options that were selected should stay checked.
For example, if a user selects B, then D, and then A -
the outcome should be only D and A checked.
I'm trying to implement this logic in JS, since it doesn't work properly in R/Shiny.
The main reason is that updating the input doesn't occur immediately.
(it is delayed by other invalidations in my original Shiny app, that take quite some time)
Minimal example:
library(shiny)
shinyApp(
ui = fluidPage(
tags$script(
"JS code here..."
),
checkboxGroupInput(
inputId = "the_checkbox",
label = "Checkbox",
choices = c("A", "B", "C", "D")
)
),
server = function(input, output, session) {}
)
javascript jquery r checkbox shiny
javascript jquery r checkbox shiny
asked Nov 23 '18 at 15:34
yanirmoryanirmor
205212
205212
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Note: The HTML you produce likely looks different, but the JS you need is most certainly the same. Everything is written in vanilla JS, in case you usually use jQuery, all you need to change is the "activation" code at the end.
Given this HTML:
<div class="inputgroup">
<div class="checkbox">
<input type="checkbox" name="check1" value="A" id="c1">
<label for="c1">A</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check2" value="B" id="c2">
<label for="c2">B</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check3" value="C" id="c3">
<label for="c3">C</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check4" value="D" id="c4">
<label for="c4">D</label>
</div>
</div>
The JS code to do it is pretty simple (plenty of comments to explain what's going on):
function justTwo (checkboxGroup) {
// checkboxGroup is the <div class="inputgroup"> node
// ---------
// step 1: grab all <input> elements inside the group
var boxes = Array.prototype.slice.call(checkboxGroup.querySelectorAll('input'));
// step 2: create a list, where nodes which are checked are stored
var checked = ;
// step 3: create a function which unchecks boxes from the beginning
// of the list if a third checkbox is checked
function handleCheckedChange (event) {
if (event.target.checked) { // if the user checked the box...
if (checked.length >= 2) { // ... and two or more boxes are checked already ...
var fst = checked.shift(); // ... take the first/oldest checked ...
fst.checked = null; // ... uncheck it ...
}
checked.push(event.target); // ... and save the reference to the newly checked
} else { // if he unchecked a box ...
checked = checked.filter(function (box) { // ... remove possible references
return box !== event.target;
});
}
}
// step 4: make every <input> "listen" to check-changes
boxes.forEach(function (box) {
box.addEventListener('change', handleCheckedChange);
});
}
You then have to "activate" it on each checkbox group. This is the part I know nothing about. Hopefully it helps anyway :)
justTwo(document.querySelector('.inputgroup'));
Or with jQuery:
$('.inputgroup').each(function () { justTwo(this); });
Thank you so much! It worked very well with a little adaptation to Shiny.
– yanirmor
Nov 27 '18 at 19:11
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53449412%2fdynamic-limit-of-checkbox-group-selection%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Note: The HTML you produce likely looks different, but the JS you need is most certainly the same. Everything is written in vanilla JS, in case you usually use jQuery, all you need to change is the "activation" code at the end.
Given this HTML:
<div class="inputgroup">
<div class="checkbox">
<input type="checkbox" name="check1" value="A" id="c1">
<label for="c1">A</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check2" value="B" id="c2">
<label for="c2">B</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check3" value="C" id="c3">
<label for="c3">C</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check4" value="D" id="c4">
<label for="c4">D</label>
</div>
</div>
The JS code to do it is pretty simple (plenty of comments to explain what's going on):
function justTwo (checkboxGroup) {
// checkboxGroup is the <div class="inputgroup"> node
// ---------
// step 1: grab all <input> elements inside the group
var boxes = Array.prototype.slice.call(checkboxGroup.querySelectorAll('input'));
// step 2: create a list, where nodes which are checked are stored
var checked = ;
// step 3: create a function which unchecks boxes from the beginning
// of the list if a third checkbox is checked
function handleCheckedChange (event) {
if (event.target.checked) { // if the user checked the box...
if (checked.length >= 2) { // ... and two or more boxes are checked already ...
var fst = checked.shift(); // ... take the first/oldest checked ...
fst.checked = null; // ... uncheck it ...
}
checked.push(event.target); // ... and save the reference to the newly checked
} else { // if he unchecked a box ...
checked = checked.filter(function (box) { // ... remove possible references
return box !== event.target;
});
}
}
// step 4: make every <input> "listen" to check-changes
boxes.forEach(function (box) {
box.addEventListener('change', handleCheckedChange);
});
}
You then have to "activate" it on each checkbox group. This is the part I know nothing about. Hopefully it helps anyway :)
justTwo(document.querySelector('.inputgroup'));
Or with jQuery:
$('.inputgroup').each(function () { justTwo(this); });
Thank you so much! It worked very well with a little adaptation to Shiny.
– yanirmor
Nov 27 '18 at 19:11
add a comment |
Note: The HTML you produce likely looks different, but the JS you need is most certainly the same. Everything is written in vanilla JS, in case you usually use jQuery, all you need to change is the "activation" code at the end.
Given this HTML:
<div class="inputgroup">
<div class="checkbox">
<input type="checkbox" name="check1" value="A" id="c1">
<label for="c1">A</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check2" value="B" id="c2">
<label for="c2">B</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check3" value="C" id="c3">
<label for="c3">C</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check4" value="D" id="c4">
<label for="c4">D</label>
</div>
</div>
The JS code to do it is pretty simple (plenty of comments to explain what's going on):
function justTwo (checkboxGroup) {
// checkboxGroup is the <div class="inputgroup"> node
// ---------
// step 1: grab all <input> elements inside the group
var boxes = Array.prototype.slice.call(checkboxGroup.querySelectorAll('input'));
// step 2: create a list, where nodes which are checked are stored
var checked = ;
// step 3: create a function which unchecks boxes from the beginning
// of the list if a third checkbox is checked
function handleCheckedChange (event) {
if (event.target.checked) { // if the user checked the box...
if (checked.length >= 2) { // ... and two or more boxes are checked already ...
var fst = checked.shift(); // ... take the first/oldest checked ...
fst.checked = null; // ... uncheck it ...
}
checked.push(event.target); // ... and save the reference to the newly checked
} else { // if he unchecked a box ...
checked = checked.filter(function (box) { // ... remove possible references
return box !== event.target;
});
}
}
// step 4: make every <input> "listen" to check-changes
boxes.forEach(function (box) {
box.addEventListener('change', handleCheckedChange);
});
}
You then have to "activate" it on each checkbox group. This is the part I know nothing about. Hopefully it helps anyway :)
justTwo(document.querySelector('.inputgroup'));
Or with jQuery:
$('.inputgroup').each(function () { justTwo(this); });
Thank you so much! It worked very well with a little adaptation to Shiny.
– yanirmor
Nov 27 '18 at 19:11
add a comment |
Note: The HTML you produce likely looks different, but the JS you need is most certainly the same. Everything is written in vanilla JS, in case you usually use jQuery, all you need to change is the "activation" code at the end.
Given this HTML:
<div class="inputgroup">
<div class="checkbox">
<input type="checkbox" name="check1" value="A" id="c1">
<label for="c1">A</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check2" value="B" id="c2">
<label for="c2">B</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check3" value="C" id="c3">
<label for="c3">C</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check4" value="D" id="c4">
<label for="c4">D</label>
</div>
</div>
The JS code to do it is pretty simple (plenty of comments to explain what's going on):
function justTwo (checkboxGroup) {
// checkboxGroup is the <div class="inputgroup"> node
// ---------
// step 1: grab all <input> elements inside the group
var boxes = Array.prototype.slice.call(checkboxGroup.querySelectorAll('input'));
// step 2: create a list, where nodes which are checked are stored
var checked = ;
// step 3: create a function which unchecks boxes from the beginning
// of the list if a third checkbox is checked
function handleCheckedChange (event) {
if (event.target.checked) { // if the user checked the box...
if (checked.length >= 2) { // ... and two or more boxes are checked already ...
var fst = checked.shift(); // ... take the first/oldest checked ...
fst.checked = null; // ... uncheck it ...
}
checked.push(event.target); // ... and save the reference to the newly checked
} else { // if he unchecked a box ...
checked = checked.filter(function (box) { // ... remove possible references
return box !== event.target;
});
}
}
// step 4: make every <input> "listen" to check-changes
boxes.forEach(function (box) {
box.addEventListener('change', handleCheckedChange);
});
}
You then have to "activate" it on each checkbox group. This is the part I know nothing about. Hopefully it helps anyway :)
justTwo(document.querySelector('.inputgroup'));
Or with jQuery:
$('.inputgroup').each(function () { justTwo(this); });
Note: The HTML you produce likely looks different, but the JS you need is most certainly the same. Everything is written in vanilla JS, in case you usually use jQuery, all you need to change is the "activation" code at the end.
Given this HTML:
<div class="inputgroup">
<div class="checkbox">
<input type="checkbox" name="check1" value="A" id="c1">
<label for="c1">A</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check2" value="B" id="c2">
<label for="c2">B</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check3" value="C" id="c3">
<label for="c3">C</label>
</div>
<div class="checkbox">
<input type="checkbox" name="check4" value="D" id="c4">
<label for="c4">D</label>
</div>
</div>
The JS code to do it is pretty simple (plenty of comments to explain what's going on):
function justTwo (checkboxGroup) {
// checkboxGroup is the <div class="inputgroup"> node
// ---------
// step 1: grab all <input> elements inside the group
var boxes = Array.prototype.slice.call(checkboxGroup.querySelectorAll('input'));
// step 2: create a list, where nodes which are checked are stored
var checked = ;
// step 3: create a function which unchecks boxes from the beginning
// of the list if a third checkbox is checked
function handleCheckedChange (event) {
if (event.target.checked) { // if the user checked the box...
if (checked.length >= 2) { // ... and two or more boxes are checked already ...
var fst = checked.shift(); // ... take the first/oldest checked ...
fst.checked = null; // ... uncheck it ...
}
checked.push(event.target); // ... and save the reference to the newly checked
} else { // if he unchecked a box ...
checked = checked.filter(function (box) { // ... remove possible references
return box !== event.target;
});
}
}
// step 4: make every <input> "listen" to check-changes
boxes.forEach(function (box) {
box.addEventListener('change', handleCheckedChange);
});
}
You then have to "activate" it on each checkbox group. This is the part I know nothing about. Hopefully it helps anyway :)
justTwo(document.querySelector('.inputgroup'));
Or with jQuery:
$('.inputgroup').each(function () { justTwo(this); });
answered Nov 23 '18 at 17:15
DavidDavid
1,086116
1,086116
Thank you so much! It worked very well with a little adaptation to Shiny.
– yanirmor
Nov 27 '18 at 19:11
add a comment |
Thank you so much! It worked very well with a little adaptation to Shiny.
– yanirmor
Nov 27 '18 at 19:11
Thank you so much! It worked very well with a little adaptation to Shiny.
– yanirmor
Nov 27 '18 at 19:11
Thank you so much! It worked very well with a little adaptation to Shiny.
– yanirmor
Nov 27 '18 at 19:11
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53449412%2fdynamic-limit-of-checkbox-group-selection%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown