- 
                Notifications
    
You must be signed in to change notification settings  - Fork 1.9k
 
Closed
Description
Consider a basic input binding:
# app.R
library(shiny)
incrementButton <- function(inputId, value = 0) {
  tagList(
    tags$head(tags$script(src = "increment.js")),
    tags$button(id = inputId,
                class = "increment btn btn-default",
                type = "button",
                as.character(value))
  )
}
ui <- fluidPage(
  incrementButton("foo"),
  textOutput("foo_value")
)
server <- function(input, output, session) {
  output$foo_value <- renderText({
    paste("Clicked this many times:", input$foo)
  })
}
shinyApp(ui, server)// www/increment.js
$(document).on("click", "button.increment", function(evt) {
  // evt.target is the button that was clicked
  var el = $(evt.target);
  // Set the button's text to its current value plus 1
  el.text(parseInt(el.text()) + 1);
  // Raise an event to signal that the value changed
  el.trigger("change");
});
var incrementBinding = new Shiny.InputBinding();
$.extend(incrementBinding, {
  find: function(scope) {
    return $(scope).find(".increment");
  },
  getValue: function(el) {
    return parseInt($(el).text());
  },
  setValue: function(el, value) {
    $(el).text(value);
  },
  subscribe: function(el, callback) {
    $(el).on("change.incrementBinding", function(e) {
      callback();
    });
  },
  unsubscribe: function(el) {
    $(el).off(".incrementBinding");
  }
});Now, if we register synchronously all is fine, but not if we register in a setTimeout(), the binding doesn't bind to the DOM:
setTimeout(() => { Shiny.inputBindings.register(incrementBinding); }, 100);That use case may seem contrived, but becomes a real problem if you're trying to load JS dependencies asynchronously (e.g., via requirejs) to define/register the binding:
incrementButton <- function(inputId, value = 0) {
  tagList(
    tags$head(
      tags$script(src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"
      tags$script(src = "increment.js")
    ),
    tags$button(id = inputId,
                class = "increment btn btn-default",
                type = "button",
                as.character(value))
  )
}require.config({paths: {"lodash": "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min"}});
require(["lodash"], function(_) {
  const finalBinding = _.last([incrementBinding]);
  Shiny.inputBindings.register(finalBinding);
})Metadata
Metadata
Assignees
Labels
No labels