harveyl888 / shinyExtra

Some additional functions for shiny apps
3 stars 0 forks source link

Initialization fails when creating an SXSortable widget using renderUI #4

Closed harveyl888 closed 7 years ago

harveyl888 commented 7 years ago

Initial values of SXSortable can be accessed within a shiny app when the widget is created in ui. If it's created through uiOutput, though, the initial values are not accessible until a change is made to fire an update.

harveyl888 commented 7 years ago

It's a little hacky but it seems to work...

First, the initial values are attached to the sortGroupOuter containers as data attributes (data-value).

Then the following is added at the beginning of the server code:

  session$onFlushed(function() {
    session$sendCustomMessage(type = "initSort", 1)
  }, once=TRUE)

This forces the javascript function initSort to be called the next time shiny flushes the reactive system. The javascript function below is included in shinyExtra.js:

Shiny.addCustomMessageHandler("initSort", function(dummy) {
  var sortOuter = $(".sortGroupOuter");
  sortOuter.each(function(x) {
    var initData = $(this).data("value");
    var outerid = $(this).prop("id");
    var shinyid = outerid.substring(0, outerid.indexOf("_")) + "_val" + outerid.substring(outerid.indexOf("_"));
    Shiny.onInputChange(shinyid, initData);
  });
});

The javascript code pulls the initial values from the data-value attribute and assigns them to the correct shiny variable. An example can be found in https://github.com/harveyl888/shinyExtra/tree/master/inst/examples/example02

Like I said, a little hacky for now and it's only needed when the widget is created using renderUI.

harveyl888 commented 7 years ago

A better use of the session$onFlushed method is to include it in the renderUI code directly. For example:

output$uisort2 <- renderUI({
    session$onFlushed(function() {
      session$sendCustomMessage(type = "initSort", 1)
    }, once=TRUE)
    SXSortable('sort2', labels = list(list("label 1", "label 2", "label 3"), list("label 4", "label 5")), styleclass = list("success", "primary"), headers=list("title 1", "title 2"), colorByGroup = TRUE, height = 100)
  })

This ensures that initSort is rerun whenever the data in sort2 is changed.