Checkboxbar with maximum choices limitation

2

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.

Jake Pan

Posted 2017-07-26T07:52:46.177

Reputation: 384

Question was closed 2017-07-26T13:58:41.773

You have to add Dynamic to the argument of Enabled, i.e. CheckboxBar[Dynamic[x], {1, 2, 3, 4}, Enabled :> Dynamic[Length@x < 3]] – JEM_Mosig – 2017-07-26T08:01:21.357

3Maybe this would work for you? CheckboxBar[ Dynamic[x, (x = Reverse[Take[Reverse[#], UpTo[2]]]) &], {1, 2, 3, 4}] – Kuba – 2017-07-26T08:39:22.203

@Kuba♦ , Thanks! This is a quite clever way! – Jake Pan – 2017-07-26T08:59:44.170

1

Is this a duplicate or do you need something more? Selection Limit on CheckboxBar

– Kuba – 2017-07-26T09:37:34.523

@Kuba I think it could be a duplicate of that one. – Edmund – 2017-07-26T10:52:57.067

Answers

2

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

JEM_Mosig

Posted 2017-07-26T07:52:46.177

Reputation: 2 559

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. – Jake Pan – 2017-07-26T08:17:20.407

You should add this to your question. – JEM_Mosig – 2017-07-26T09:17:34.940