2
$\begingroup$

This question already has an answer here:

I am a novice to interactive interface with Dynamic and other stuff. So don't blame on me if I ask idiot questions.

What I want is to set a checkbox and set a limitation for the maximal number that choices can be checked. For example, say I have a checkboxbar like:

CheckboxBar[Dynamic[x],{1,2,3,4}]

Now I am able to check as many choices as I like. But what if I only want to check at most two box? Is there a way to let me check the first two boxes and then the remaining unchecked one will automatically become gray(not clickable, just like the option:Enabled->False)

My naive idea was:

CheckboxBar[Dynamic[x],{1,2,3,4},Enabled->If[Length@x<2,True,False]]

But it doesn't work.

Thanks for your time! Any comments and suggestions are very welcome.

$\endgroup$

marked as duplicate by Edmund, LCarvalho, m_goldberg, MarcoB, yohbs Jul 26 '17 at 13:58

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\begingroup$ You have to add Dynamic to the argument of Enabled, i.e. CheckboxBar[Dynamic[x], {1, 2, 3, 4}, Enabled :> Dynamic[Length@x < 3]] $\endgroup$ – JEM_Mosig Jul 26 '17 at 8:01
  • 3
    $\begingroup$ Maybe this would work for you? CheckboxBar[ Dynamic[x, (x = Reverse[Take[Reverse[#], UpTo[2]]]) &], {1, 2, 3, 4}] $\endgroup$ – Kuba Jul 26 '17 at 8:39
  • $\begingroup$ @Kuba♦ , Thanks! This is a quite clever way! $\endgroup$ – Jake Pan Jul 26 '17 at 8:59
  • 1
    $\begingroup$ Is this a duplicate or do you need something more? Selection Limit on CheckboxBar $\endgroup$ – Kuba Jul 26 '17 at 9:37
  • $\begingroup$ @Kuba I think it could be a duplicate of that one. $\endgroup$ – Edmund Jul 26 '17 at 10:52
2
$\begingroup$

You almost got it right. This should do what you want:

CheckboxBar[Dynamic[x], {1, 2, 3, 4}, Enabled -> Dynamic[Length[x] < 3]]

Besides the Dynamic after Enabled, which is the thing that makes everything work, I also shortened your If statement, using that Length[x] < 3 already returns either True or False (unless you do something strange with x -- if that can happen, you may want to wrap Length[x] < 3 into TrueQ). To re-enable the bar once it was disabled, you could add a Button to your notebook, such as

Button["Reset", x = {}]

Addendum

Following up on your comment. A CheckboxBar where only the checkboxes get disabled that would, when clicked, exceed the limit, can be built from individual Checkboxes, e.g.:

With[{labels = {"a", "b", "c", "d"}},
  DynamicModule[{x, arr, bar, n = Length[labels]},
    x = Array[arr, n];
    bar = (
      Checkbox[Dynamic[#],
        Enabled -> Dynamic[
          Count[Table[arr[i], {i, n}], True] < 2 || TrueQ[#]
        ]
      ] & /@ x
    );
    (* initialize *)
    Do[arr[i] = False, {i, n}];
    (* return the bar *)
    Row[Riffle[bar, labels], Spacer[10]]
  ]
]

dynamic checkbox-bar output

$\endgroup$
  • $\begingroup$ Thanks for your prompt answer! It does work. But I am sorry, I forgot to say one thing, that is once it is disabled, all the choices are disabled, which is not my intention. I expect it to only disable the remaining unchecked one, so that I can change my choices later if I check the wrong box by clicking again to un-check. Would it be possible? I tried something like Enable->{True,True,False,False} but it seems there is no such grammar to assign the checkability separately. $\endgroup$ – Jake Pan Jul 26 '17 at 8:17
  • $\begingroup$ You should add this to your question. $\endgroup$ – JEM_Mosig Jul 26 '17 at 9:17

Not the answer you're looking for? Browse other questions tagged or ask your own question.