-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider making Shiny's default binding inputs less inclusive #2956
Comments
Thanks for the feedback. I agree with this. The earliest conception of Shiny involved app authors writing raw HTML directly, and in an effort to make that HTML as concise as possible, I made it so that explicit classes were not required. Given how Shiny turned out, this was the wrong choice but we've left this behavior for backward compatibility reasons. Going forward I could imagine a couple of ways to improve the situation without breaking backward compatibility.
|
Thanks, as a reference my current workaround (after many attempts) is this:
That's similar to your first proposal. To that context, alternatively of a class, it could be just a simple flag attribute, like data-shiny-ignore, where its presence would exclude the binding:
That approach would require minimal changes and only to the Javascript code of the input bindings (or perhaps just in On the other hand your second proposal feels closer to the correct approach: using custom classes. |
I am having a similar issue, in which I am creating several Therefore, I was wondering if there is any official support for the Thanks a lot for your help! $(function() {
// Input binding
let myInputBinding = new Shiny.InputBinding();
$.extend(myInputBinding, {
initialize: function(el) {
console.log("Initializing")
let choices = JSON.parse($(el).attr("data-init_choices"));
let ns = $(el).attr("id")
for(let k in choices){
let subel = $(`<select name=${k} data-input-id = ${ns}></select>`).append()
let v = choices[k]
v.map((x)=>$(subel).append(`<option value = ${x}>${x}</option>`))
$(el).append(subel)
}
},
find: function(scope) {
return $(scope).find('.hier_select');
},
getValue: function(el) {
let selection = {}
$(el).children("select").each(function(x){
selection[$(this).attr("name")] = $(this).val()
})
return JSON.stringify(selection)
},
getType: function(el) {
return "hier_select.listOutput";
},
subscribe: function(el, callback) {
$(el).on("change.hier_select select", function(event){
callback();
})
}
});
Shiny.inputBindings.register(myInputBinding, "my_inputs.hier_select");
});
<div class="form-group shiny-input-container">
<div id="my_input" class="hier_select shiny-bound-input" data-init_choices="{'A':['a'],'B':['b','h','j'],'C':['c']}">
<select name="A" data-input-id="my_input">
<option value="a">a</option>
</select>
<select name="B" data-input-id="my_input">
<option value="b">b</option>
<option value="h">h</option>
<option value="j">j</option>
</select>
<select name="C" data-input-id="my_input">
<option value="c">c</option>
</select>
</div>
</div> |
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: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
: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:
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: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.
The text was updated successfully, but these errors were encountered: