#r #shiny
Вопрос:
У меня возникли проблемы при работе с renderUI в Shiny.
В приведенном ниже коде MWE у пользователя есть возможность изменить входные данные для слайдера ( periods
) и первой сетки матрицы ( base_input
) из их значений по умолчанию (для этого MWE активирована только 1-я строка этой матрицы x1, строка «A»).
Пользователь также может создать многопеременный вектор для этой переменной «A», нажав кнопку «Показать» и вставив значения во 2-ю матрицу ( vector_input
), которая появляется на той же боковой панели. Это прекрасно работает. По мере изменения входных данных в ползунке и первой строке/столбце матрицы x1 (если матрица x2 появилась, нажав «Показать»), 1-я строка матрицы x2 отражает эти изменения реактивно, что и должно работать. (Обратите внимание, что для ввода в эту 2 — ю матрицу вы должны 1-й раз щелкнуть и ввести в правый столбец перед вводом в левый столбец-это связано с незначительной ошибкой в shinyMatrix, для которой у меня есть исправление, но еще не реализовано).
Мой вопрос: как я могу адаптировать это так, чтобы изменения в слайдере и матрице x1 отражались в матрице x2 ПЕРЕД нажатием кнопки ПОКАЗАТЬ, которая запускает renderUI?
Поэтому, если пользователь внес какие-либо изменения во входные данные слайдера/матрицы x1 перед нажатием кнопки ПОКАЗАТЬ, а затем нажал кнопку ПОКАЗАТЬ, то эти изменения в слайдере/матрице x1 уже отражены в матрице x2.
Кажется, что приведенное ниже событие, связывающее слайдер/матрицу x1 с матрицей x2, должно быть встроено в раздел renderUI, чтобы выполнить вышеуказанную работу, но когда я пытаюсь это сделать, это не работает. Есть какие-нибудь решения?
Кроме того, я не хочу нажимать на кнопку «Скрыть», чтобы сбросить значения по умолчанию в этой матрице 2.
Я публикую несколько изображений ниже, чтобы сделать это более понятным.
Ниже приведен код MWE:
library(shiny)
library(shinyMatrix)
library(shinyjs)
ui <-
pageWithSidebar(
headerPanel("Model..."),
sidebarPanel(
conditionalPanel(condition="input.tabselected==2",
sliderInput('periods','',min=1,max=120,value=60),
matrixInput(
"base_input",
value = matrix(c(0.2), 4, 1, dimnames = list(c("A","B","C","D"),NULL)),
rows = list(extend = FALSE, names = TRUE),
cols = list(extend = FALSE, names = FALSE, editableNames = FALSE),
class = "numeric"),
h5(strong("Vectorize variables:")), # Adds a line of text
# Action buttons to conditionally show/hide performance vectors:
useShinyjs(),
actionButton('showPerfVectorBtn','Show',style="width:9vw"),
actionButton('hidePerfVectorBtn','Hide',style="width:9vw"),
uiOutput("Vectors")
)), # close conditional and sidebar panels
mainPanel(
tabsetPanel(
tabPanel("Dynamic", value=2,
helpText("Dynamic B")),
id = "tabselected"))
) # close page with sidebar
server <- function(input,output,session)({
# --- Set reactive input variables
periods <- reactive(input$periods)
base_input <- reactive(input$base_input)
vector_input <- reactive(input$vector_input)
# --- Link first row of vector input grids to base_input matrix
observeEvent(input$periods|input$base_input,{
updateMatrixInput(session,"vector_input",
value=matrix(c(input$periods,input$base_input[1,1]),1,2,
dimnames=list(NULL, c("Y","Z")))
) # close update matrix
}) # close observe event
# --- Action buttons to conditionally show/hide performance vectors
output$Vectors <- renderUI({
req(input$showPerfVectorBtn)
tagList(
matrixInput(
"vector_input",
value = matrix(c(1,0.2),1,2,dimnames=list(NULL,c("Y","Z"))),
rows = list(extend = TRUE, names = FALSE),
cols = list(extend = FALSE, names = TRUE, editableNames = FALSE),
class = "numeric")
) # close tag list
}) # close render UI
observeEvent(input$showPerfVectorBtn,{shinyjs::show("Vectors")})
observeEvent(input$hidePerfVectorBtn,{shinyjs::hide("Vectors")})
# --- Captures inputs as global variables
observeEvent(periods(), {periods.R <<- periods()})
observeEvent(base_input(), {base_input.R <<- base_input()})
observeEvent(vector_input(), {vector_input.R <<- vector_input()})
}) # close server section
shinyApp(ui, server)
Ответ №1:
Решение намного проще, чем я думал. Я повозился с ним еще немного, внимательно посмотрел на код, чтобы убедиться, что понимаю.
В matrixInput
функции, в renderUI
функции Server
раздела в коде MWE, опубликованном выше, см. строку, которая гласит value = matrix(c(1,0.2),1,2,dimnames=list(NULL,c("Y","Z")))
.
Чтобы это сработало, как описано выше, просто измените определение матрицы в этой строке С c(1,0.2)
НА c(input$periods,input$base_input[1,1])
. Это была оплошность с моей стороны. Теперь, с этим изменением определения матрицы, первая строка значений matrix2 полностью реагирует и связана со значениями слайдера (точка) и строки матрицы A (base_input) во всех сценариях использования.