Custom Shiny Input Return List

Hi! I've made lots of custom shiny inputs but they've always returned a single value or a vector. I was wondering what the structure of my JS would need to be in order to return a list?

   ..... //shiny input binding
  getValue: function getValue(el) {
    var value = [
           {id :1, name:"a" },
           { id:2, name:"b"},
           { id:3, name"c"}
     ] 
     return value
  },

Desired Output

print(input$mything)

[[1]]
[[1]]$id
[1] 1

[[1]]$name
[1] "a"


[[2]]
[[2]]$id
[1] 2

[[2]]$name
[1] "b"


[[3]]
[[3]]$id
[1] 3

[[3]]$name
[1] "c"

What I'm getting right now:

  id name   id name   id name 
 "1"  "a"  "2"  "b"  "3"  "c" 

Bonus question! Can I give this list attributes so I can return something else from JS back to r but my user doesn't have to see it? What would that look like?

   ..... //shiny input binding
  getValue: function getValue(el) {
    var attr = "test"
    var value = [
           {id :1, name:"a" },
           { id:2, name:"b"},
           { id:3, name"c"}
     ] 
     return value
  },

So input$mything would return the same thing or something similar to this?

dummy_input <- list(list(id = 1, name = "a"), 
             list(id = 2, name = "b"), 
             list(id = 3, name = "c")
             )
attr(dummy_input, 'custom_attr') <- "test"

Hey Maya! Not sure of the specific context, but if this is in a package, I would recommend defining the .onLoad function as follows:

shiny::registerInputHandler("maya.listOutput", function(value, ...) {
    if (is.null(value)) {
      return(value)
    } else {
      df <- shiny:::safeFromJSON(value) #convert to df -- this is essentially jsonlite::fromJSON
      output <- split(df, seq(nrow(df))) #make a list of the form I think you want
      attr(output, 'custom_attr') <- "test" #add custom attribute
      return(output)
    }
  }, force = TRUE) #force = TRUE so error message doesn't appear when the input handler is already loaded

Then in your custom input binding, you would want to change your getValue method to this (just change the output to a JSON string):

getValue: function getValue(el) {
 var value = [
           { id :1, name:"a" },
           { id:2, name:"b"},
           { id:3, name: "c"}
     ]
   return(JSON.stringify(value));
},

The last step is to add a getType method in your custom binding. This will tell Shiny that it should return to the user what data as you defined it.

getType: function(el) {
    return "maya.listOutput";
  }

Sample output is below, and I believe it is equivalent to what you want. If not, you can change the expected output in your input handler.

[[1]]
  id name
1  1    a

[[2]]
  id name
2  2    b

[[3]]
  id name
3  3    c

attr(,"custom_attr")
[1] "test"

This book was really helpful, as was the documentation for registerInputHandler. I hope that helps?!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.