SelectizeInput внутри DT :: datatable работает только как html - PullRequest
3 голосов
/ 29 мая 2020

Я пытаюсь оптимизировать UX для моего конечного пользователя в приложении для отслеживания времени. По сути, он извлекает данные из api календаря Google, упорядочивает их в tibble и позволяет пользователю выбирать / отменять выбор / редактировать собрания и назначать их проектам. Проекты выбираются в раскрывающемся меню, которое я использовал для сборки selectizeInput, но получаю что-то похожее на selectInput

. Я хочу использовать shiny::selectizeInput внутри DT::datatable в Shiny. Я могу заставить раскрывающийся список работать. Однако я теряю функцию поиска, которая поставляется с вводом выбора. В моем примере с игрушкой верхний selectizeInput, который вы можете щелкнуть и ввести параметры, которые вы ищете. Тот, который находится в таблице данных, вы все равно можете это сделать, но со сложными именами для UX было бы лучше, если бы вы могли видеть, что вы набираете.

Я обнаружил эту проблему в репозитории github, где производитель пакета DT сказал, что подобное может быть невозможно. Впрочем, ему 3 года, может кто придумал обходной путь. https://github.com/rstudio/DT/issues/390

Я также пробовал перейти на другой тип пользовательского интерфейса, tuicalendr, который для моих целей отлично работает, но столкнулся с той же проблемой. Мой опыт работы с JS ограничен, поэтому у меня возникли проблемы с настройкой JS в Shiny.

library(shiny)
library(DT)

ui <- fluidPage(
  selectizeInput("input", 
                 label = "",
                 choices = letters[1:26],
                 selected = letters[1]),
DTOutput("datatable")
)


server <- function(input, output) {

output$datatable<- renderDataTable({
  DT::datatable(data.frame(a = as.character(selectizeInput("dtinput",
                                label = "",
                                choices = letters[1:26],
                                selected = letters[1]),
             stringsAsFactors = F)),
             escape = F)
})


}

# Run the application 
shinyApp(ui = ui, server = server)

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

1 Ответ

3 голосов
/ 05 июня 2020

Необходимо добавить функциональность javascript вручную. Соответствующий код будет: $('#ID').selectize().

Чтобы получить требуемый код html для добавления, вы можете запустить: withTags(selectInput(inputId = "mselect", label = "multi", choices = letters[1:3], multiple = TRUE)). Вы можете извлечь оттуда необходимую часть html.

В документе вы обнаружите, что вы можете передать код javascript с помощью JS(): the character options wrapped in JS() will be treated as literal JavaScript code instead of normal character strings.

Вы хотите добавьте код javascript после визуализации выбранной части. Это обеспечивается с помощью опции initcomplete.

Чтобы использовать значения из ввода, вы должны привязать их к shiny:

preDrawCallback = JS('function(){Shiny.unbindAll(this.api().table().node());}'),
drawCallback = JS('function(){Shiny.bindAll(this.api().table().node());}')

Как упоминал Ремко в своем связанном посте очень полезно. Практически вся эта информация доступна в посте. Для создания воспроизводимого примера может потребоваться некоторый опыт в блестящем освещении, поэтому я добавил его для вас:

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

library(shiny)
library(DT)

ui <- fluidPage(

  selectizeInput(
    inputId = "input",
    label = "",
    choices = letters[1:26],
    selected = letters[1]
  ),

  fluidRow(
    DTOutput(outputId = "table")
  )

)

#withTags(selectInput(inputId = "mselect", label = "multi", choices = letters[1:3], 
#    multiple = TRUE))
df <- data.frame(mselect = 
  '<select id="mselect" class="form-control" multiple="multiple">
     <option value="car">car</option>
     <option value="cars">cars</option>
     <option value="dog">dog</option>
  </select>'  
)


js <- c(
  "function(settings){",
  "  $('#mselect').selectize()",
  "}"
)

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

  observe({
    print(input$mselect)
  })

  output$table <- renderDT({

    datatable(
      data = df,
      escape = FALSE,
      options = 
        list(
          initComplete = JS(js),
          preDrawCallback = JS('function(){Shiny.unbindAll(this.api().table().node());}'),
          drawCallback = JS('function(){Shiny.bindAll(this.api().table().node());}')
      )
    )

  })

}

shinyApp(ui = ui, server = server)
...