#r #shiny
#r #блестящий
Вопрос:
в идеале мое мини-приложение должно работать следующим образом:
-
Пользователь выбирает имя из списка ранее существовавших имен;
-
Если имя, которое имеет в виду пользователь, отсутствует в списке, появится окно открытого типа, в котором пользователь может ввести новое имя;
-
Пользователь нажимает кнопку действия «Показать выбранное имя», и любое выбранное или введенное имя отображается на главной панели;
-
Другая кнопка действия «Показать количество символов» появляется только после нажатия кнопки «Показать выбранное имя» — но только если имя выбрано из списка ИЛИ если поле открытого конца для имени, предоставленного пользователем, не пустое. Если пользователь нажимает эту новую кнопку, отображается количество символов в выбранном имени.
Я не могу заставить последний пункт работать: как я мог бы заставить вторую кнопку появляться, ТОЛЬКО если выбранное (или введенное) имя НЕ является пустым и исчезает, как только пользователь случайно удаляет все в окне открытого доступа?
Большое вам спасибо! Ниже приведен мой код:
library(shiny)
ui = shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("name_fromlist", "Select a name", choices = ""),
uiOutput("open_end")
),
mainPanel(
textOutput("name_final"), br(),
actionButton("button1", label = "Show chosen name"), br(),
textOutput('final_name'),
uiOutput("second_button") # it should show number of characters in the chosen name
)
)
))
server = shinyServer(function(input, output, session) {
# A vector of pre-existing names:
mynames <- c("John", "Mary", "Jim", "Bill")
# Pull-down to select one of the names:
observe({
updateSelectInput(session, inputId = "name_fromlist", label = "Select a name:",
choices = c(mynames, "Name not on our list"))
})
# Open end box to appear only if the name the user wants to enter is not on the list:
output$open_end <- renderUI({
if (!input$name_fromlist == 'Name not on our list') return(NULL) else {
textInput("Not_on_list", "If the name you want is not on our list, type it here:")
}
})
# button 1 shows the name selected or typed:
observeEvent(input$button1, {
if (input$name_fromlist == 'Name not on our list') selected_name <- input$Not_on_list else {
selected_name <- input$name_fromlist
}
output$final_name <- renderText({paste("Chosen name: ", selected_name)})
})
# # This part is not working:
# observe({
# if (input$name_fromlist == 'Name not on our list' amp; input$Not_on_list == '') renderUI({NULL}) else {
# output$add_user <- renderUI({
# actionButton("second_button", label = "Show number of characters")
# })
# } # end of else
# }) # end of observe
})
shinyApp(ui = ui, server = server)
Ответ №1:
Вы можете попробовать использовать conditionalPanel
и вам нужно будет создать другую observeEvent
для управления этой второй кнопкой.
library(shiny)
ui = shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("name_fromlist", "Select a name", choices = ""),
uiOutput("open_end")
),
mainPanel(
textOutput("name_final"), br(),
actionButton("button1", label = "Show chosen name"), br(),
textOutput('final_name'),
#### Second Button ####
# to only appear if name from the list is chosen or Name not on the list is not empty
conditionalPanel(condition = "(input.name_fromlist != '' amp; input.name_fromlist != 'Name not on our list') |input.Not_on_list != ''",
actionButton("button2", label = "Show number of characters")),
# Display number of characters for the chosen names
textOutput("no_of_char")
)
)
))
server = shinyServer(function(input, output, session) {
# A vector of pre-existing names:
mynames <- c("John", "Mary", "Jim", "Bill")
# Pull-down to select one of the names:
observe({
updateSelectInput(session, inputId = "name_fromlist", label = "Select a name:",
choices = c(mynames, "Name not on our list"))
})
# Open end box to appear only if the name the user wants to enter is not on the list:
output$open_end <- renderUI({
if (!input$name_fromlist == 'Name not on our list') return(NULL) else {
textInput("Not_on_list", "If the name you want is not on our list, type it here:")
}
})
# button 1 shows the name selected or typed:
observeEvent(input$button1, {
if (input$name_fromlist == 'Name not on our list') selected_name <- input$Not_on_list else {
selected_name <- input$name_fromlist
}
output$final_name <- renderText({paste("Chosen name: ", selected_name)})
})
#### observeEvent for Second Button
## This is to display number of charactesr based on chosen/typed names
observeEvent(input$button2, {
if (input$name_fromlist == "Name not on our list") {
selected_name <- input$Not_on_list
} else {
selected_name <- input$name_fromlist
}
output$no_of_char <- renderText({paste("Number of Characters: ", nchar(selected_name))})
})
})
shinyApp(ui = ui, server = server)
Комментарии:
1. Большое вам спасибо. Он закрыт, но есть одна маленькая проблема: как только приложение запускается, появляется кнопка 2, но я бы хотел, чтобы она отображалась только после нажатия кнопки 1.
2. Жаль, что нельзя помещать код в комментарии. В вашем решении я заменил кнопку действия 2 на стороне пользовательского интерфейса на uiOutput («button2»). И на стороне сервера, внутри observeEvent (введите $button1… Я добавил вывод $button2 <- renderUI({ actionButton(«button2», … — так что теперь кнопка 2 появляется только после нажатия кнопки 1. И он исчезает, если поле с открытым концом пусто. Но у нас все еще есть проблема: кнопка 2 появляется снова, как только открытый конец заполнен — и ДО того, как кнопка 1 будет нажата снова. Я понимаю, что это непростая задача: но возможно ли заставить его снова появиться ТОЛЬКО после повторного нажатия кнопки 1? Спасибо!
3. Похоже, я нашел решение — использовать observate вместо этой условной панели
4. К сожалению, у меня была возможность взглянуть на это только сегодня. Да, это работает хорошо.
Ответ №2:
Похоже, я нашел решение — без условной панели. Обратите внимание, что вторая кнопка исчезает, если поле открытого конца пустое:
library(shiny)
# A vector of pre-existing names:
mynames <- c("John", "Mary", "Jim", "Bill")
ui = shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("name_fromlist", "Select a name", choices = c(mynames, "Name not on our list")),
uiOutput("open_end")
),
mainPanel(
textOutput("name_final"), br(),
actionButton("button1", label = "Show chosen name"),
br(),
textOutput('final_name'), br(),
uiOutput("button2"),
br(),
# Display number of characters for the chosen names
conditionalPanel(condition = " input.name_fromlist != 'Name not on our list' |
input.Not_on_list != '' ",
textOutput("no_of_char")
)
)
)
))
server = shinyServer(function(input, output, session) {
# Open end box to appear only if the name the user wants to enter is not on the list:
output$open_end <- renderUI({
if (!input$name_fromlist == 'Name not on our list') return(NULL) else {
textInput("Not_on_list", "If the name you want is not on our list, type it here:")
}
})
# button 1 shows the name selected or typed:
observeEvent(input$button1, {
if (input$name_fromlist == 'Name not on our list') selected_name <- input$Not_on_list else {
selected_name <- input$name_fromlist
}
output$final_name <- renderText({paste("Chosen name: ", selected_name)})
output$button2 <- renderUI({
actionButton("button2", label = "Show number of characters")
})
})
# This observe allows the second button to disappear:
observe({
if (!is.null(input$Not_on_list)) {
if (input$name_fromlist == 'Name not on our list' amp; input$Not_on_list == '') {
output$button2 <- renderUI({NULL})
}
}
})
#### observeEvent for Second Button
## This is to display number of charactesr based on chosen/typed names
observeEvent(input$button2, {
if (input$name_fromlist == "Name not on our list") {
selected_name <- input$Not_on_list
} else {
selected_name <- input$name_fromlist
}
output$no_of_char <- renderText({paste("Number of Characters: ", nchar(selected_name))})
})
})
shinyApp(ui = ui, server = server)