-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
While I'm developing custom Shiny inputs, I've noticed that some Shiny's default binding inputs are too inclusive, as in find method they search for every input element in the page:
For example, look at checkboxInputBinding find method:
find: function(scope) {
return $(scope).find('input[type="checkbox"]');
},
It tries to register a binding for every checkbox input element.
The behavior is similar for textInputBinding, numberInputBinding, passwordInputBinding, selectInputBinding, textareaInputBinding
On the other hand there are other input bindings that look for a custom class, for example radioInputBinding:
find: function(scope) {
return $(scope).find('.shiny-input-radiogroup');
},
I believe that this is the proper way to implement the other bindings above, always using a custom class.
Of course you could argue that we could create an input binding that takes over these elements, with each own find implementation and Shiny will not create additional input.
But the problems occur when we try to create a custom Shiny input, where the html element that controls the Shiny input, is ancestor of the html element that Shiny takes control over.
For example consider a custom checkbox input binding:
<div class="custom-checkbox-input" id="scales">
<input type="checkbox" id="scalesChk"
checked>
<label for="scalesChk">Scales</label>
</div>
While my custom input binding will operate on the outer div element, Shiny will create an additional input or the checkbox input.
Similar situation occurs when using a custom control that uses a text input for example.
Let's look at textInputBinding find method:
find: function(scope) {
var $inputs = $(scope).find('input[type="text"], input[type="search"], input[type="url"], input[type="email"]');
// selectize.js 0.12.4 inserts a hidden text input with an
// id that ends in '-selectized'. The .not() selector below
// is to prevent textInputBinding from accidentally picking up
// this hidden element as a shiny input (#2396)
return $inputs.not('input[type="text"][id$="-selectized"]');
},
Here you can see the problematic situation I described.
Selectize.js inserts a hidden text input and before the fix, Shiny was creating an additional input.
That was fixed internally, but this solution is far from elegant and it does not deal with external/custom Shiny inputs that face the same problem.
All this would be fixed if a custom class is added to these problematic inputs so that they are less inclusive.
I could make a PR if you are interested.