3

Does anyone have a way to determine the type of widget from its name/ID? For example if "my_text" is a textInput widget, then I would like to be able to call:

is.textInput("my_text")

and be returned TRUE. Or to call

widget.type("my_list")

and be returned "textInput". But neither of these functions exist.

I have looked through all the functions in the shiny and shinyWidgets packages and don't see anything to this extent. There are some back-end functions like session$sendInputMessage() that are not intended for users but might assist.

My naive solution is to try something like the following (sorry if my tryCatch() syntax is not quite right, I don't use it very often):

is.textInput <- function(widget_id){
    out <- tryCatch(
        {
        # attempt to treat it as a textInput, change it and change it back
        tmp <- input[[widget_id]]
        updateTextInput(session, widget_id, value = character(0))
        updateTextInput(session, widget_id, value = tmp)
        },
        error=function(cond) { return("NO") },
        warning=function(cond) { return("NO") },
        finally={}
    )
    # if error message happens then not textInput
    if(out == "NO")
        return("FALSE")
    # if no error message then is textInput
    return("TRUE")
}

But I would rather not be creating deliberate errors/exceptions. And I do not want a logical check to be making changes to the state of the app.

Other suggests for how I might accomplish this?

Tonio Liebrand
  • 17,189
  • 4
  • 39
  • 59
Simon.S.A.
  • 6,240
  • 7
  • 22
  • 41
  • Opening a bounty on this as the browser dependence in @BigDataScientist's solution does not work with my application. – Simon.S.A. Apr 29 '19 at 00:16
  • sry to hear, could you ellaborate what is the missing functionality in your application? – Tonio Liebrand Apr 29 '19 at 14:55
  • I am not guaranteed that the user will make use of Chrome. In fact: with the IT controls on the environment, I anticipate about half of use will be via internet explorer or RStudio viewer. In the absence of a better answer, I will happily grant you the bounty - your answer has made me consider several new possibilities. – Simon.S.A. Apr 29 '19 at 20:49

1 Answers1

3

Update: I modified a line in the javascript code to make it IE/Rstudio Viewer compatible. IE/Viewer threw an error, because the function include() is not supported by them, see .includes() not working in Internet Explorer. Instead indexOf() can be used.

You could use javascript to inspect the input element by id. The element can be found via document.getElementById() and then you can identify the type via getAttribute('class') and getAttribute('type').

The results can be "sent" to R via Shiny.onInputChange('inputType', ...); and used in R via input$inputType.

A first example of the function would be:

getWidgetType <- function(widgetId){
  paste0(
    "elem = document.getElementById('", widgetId,"');
    var message;
    if(elem == null){
      message = 'No input with id = ", widgetId," exists.'
    }else{
      // RStudio Viewer + IE workaround (dont have .include())
      if(elem.getAttribute('class').indexOf('js-range-slider') > -1){ 
        message = 'slider'
      }else if (elem.nodeName == 'SELECT'){
        message = 'select'
      }else{
        message = elem.getAttribute('type');
      }
    }
    Shiny.onInputChange('inputType', message)
    "
  )
}

Note that i made an example for four inputs: numeric, text, selectInput, and sliderInput. If you add additional inputs you might have to inspect other attributes as well.

Reproducible example:

library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  textInput("textInput", "id = textInput", "text"),
  numericInput("numInput", "id = numInput", 10),
  sliderInput("slideInput", "id = slideInput", 1, 10, 5),

  hr(style = "height:1px;border:none;color:#333;background-color:#333;"),
  textInput("widgetType", "widget type by id", "textInput"),
  textOutput("widgetId")
)

server <- function(input, output, session) {

  output$widgetId <- renderText({
    runjs(getWidgetType(input$widgetType))
    input$inputType
  })

}

shinyApp(ui, server)
Wil
  • 3,076
  • 2
  • 12
  • 31
Tonio Liebrand
  • 17,189
  • 4
  • 39
  • 59
  • This solution only partially works for me. When a widget name is typed in the `widgetType` textbox, the `textOutput` does not update. Suggestions? – Simon.S.A. Apr 22 '19 at 22:38
  • somehow for me, the textoutput doesnt show in viewer pane, but it works as expected (and updates) when i open it in chrome. Which setting are you using? – Tonio Liebrand Apr 23 '19 at 21:42
  • You are right. Sorry, I was only testing in the RStudio viewer. I can confirm it works as expected in Chrome, but not in Internet Explorer (the only other browser I have on hand). – Simon.S.A. Apr 24 '19 at 03:14