определить тип виджета из имени - PullRequest
2 голосов
/ 17 апреля 2019

У кого-нибудь есть способ определить тип виджета по его имени / идентификатору? Например, если "my_text" является виджетом textInput, я хотел бы иметь возможность позвонить:

is.textInput("my_text")

и будет возвращено TRUE. Или позвонить

widget.type("my_list")

и будет возвращено "textInput". Но ни одна из этих функций не существует.

Я просмотрел все функции в пакетах shiny и shinyWidgets и ничего не вижу в этой степени. Есть некоторые фоновые функции, такие как session$sendInputMessage(), которые не предназначены для пользователей, но могут помочь.

Мое наивное решение состоит в том, чтобы попробовать что-то вроде следующего (извините, если мой синтаксис tryCatch() не совсем правильный, я его не очень часто использую):

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")
}

Но я бы не стал создавать преднамеренные ошибки / исключения. И я не хочу, чтобы логическая проверка вносила изменения в состояние приложения.

Другие подсказывают, как мне это сделать?

1 Ответ

3 голосов
/ 17 апреля 2019

Обновление: Я изменил строку в коде JavaScript, чтобы сделать его совместимым с IE / Rstudio Viewer. IE / Viewer выдал ошибку, потому что функция include() не поддерживается ими, см. .includes () не работает в Internet Explorer . Вместо этого можно использовать indexOf().

Вы можете использовать javascript для проверки элемента ввода по id. Элемент может быть найден через document.getElementById() и затем вы можете определить тип через getAttribute('class') и getAttribute('type').

Результаты могут быть "отправлены" в R через Shiny.onInputChange('inputType', ...); и использованы в R через input$inputType.

Первый пример функции:

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)
    "
  )
}

Обратите внимание, что я сделал пример для четырех входов: числовой, текстовый, selectInput и sliderInput. Если вы добавите дополнительные входные данные, возможно, вам придется проверить и другие атрибуты.

Воспроизводимый пример:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...