2016-08-23 13 views
5

Tôi đang cố gắng môđun hóa ứng dụng Sáng bóng phức tạp mà tôi có một số conditionalPanel chỉ xuất hiện cho một trạng thái đầu vào nhất định.R Mô-đun sáng bóng với điều kiệnPanel và các chất phản ứng

Trước khi tôi làm tất cả mọi thứ mô-đun, đầu vào và conditionalPanel đều trong ui.R, và tôi có thể tham khảo các đầu vào sử dụng một cái gì đó như thế này:

conditionalPanel("input.select == 'Option one'", p('Option one is selected')) 

Bây giờ tôi đã Modularized vật, tiếp cận đầu vào là phức tạp hơn. Tôi nghĩ rằng sau đây là cách để làm điều đó, nhưng nó không hoạt động. (Ở đây tôi đã kết hợp mọi thứ vào một kịch bản độc lập duy nhất):

library(shiny) 

## Module code for 'selectorUI' and 'selector' 
selectorUI <- function(id) { 
    ns <- NS(id) 
    selectizeInput(inputId = ns('select'), 
       label = 'Make a choice:', 
       choices = c('Option one', 'Option two')) 
} 

selector <- function(input, output, session) { 
    reactive(input$select) 
} 

## Main app 
ui <- shinyUI(fluidPage(
    selectorUI('id1'), 
    conditionalPanel(condition = "output.selected == 'Option one'", p('Option one is selected.')) 
)) 

server <- shinyServer(function(input, output, session) { 
    output$selected <- callModule(selector, 'id1') 
}) 

shinyApp(ui = ui, server = server) 

Tôi nghĩ rằng điều này sẽ làm việc, nhưng nó không - nó chỉ hoạt động nếu tôi làm tài liệu tham khảo khác để output$selected trong phần ui chính:

ui <- shinyUI(fluidPage(
    selectorUI('id1'), 
    textOutput('selected'), ## Adding just this one line makes the next line work 
    conditionalPanel(condition = "output.selected == 'Option one'", p('Option one is selected.')) 
)) 

Thật không may, điều này có tác dụng không mong muốn khi hiển thị kết quả là textOutput('selected'). Tôi chỉ có thể đoán rằng lý do này hoạt động là vì nó bằng cách nào đó kích hoạt phản ứng theo cách mà tham chiếu JavaScript không thôi.

Bất kỳ ý tưởng nào về cách tôi sẽ nhận được điều kiện nàyPanel hoạt động bình thường?

Cảm ơn bạn ..

EDIT: Hóa ra không thực sự là một lỗi: https://github.com/rstudio/shiny/issues/1318. Xem câu trả lời của riêng tôi dưới đây.

Nhưng cũng lưu ý rằng tôi thực sự thích giải pháp renderUI được đưa ra trong câu trả lời được chấp nhận tốt hơn cách tiếp cận ban đầu của tôi conditionalPanel.

Trả lời

4

Sau khi gọi mô-đun, ID của selectizeInputid1-select. Trong JavaScript có hai cách tiếp cận đặc tính đối tượng:

objectName.property hoặc objectName['property']

Vì không - trong ID chúng ta phải đề cập đến nó qua chuỗi, vì vậy phương pháp thứ hai là con đường để đi.

Điều kiện trong conditionalPanel trở thành:

input['id1-select'] == 'Option one' 

Full dụ:

library(shiny) 

## Module code for 'selectorUI' and 'selector' 
selectorUI <- function(id) { 
    ns <- NS(id) 
    selectizeInput(inputId = ns('select'), 
       label = 'Make a choice:', 
       choices = c('Option one', 'Option two')) 
} 

## Main app 
ui <- shinyUI(fluidPage(
    selectorUI('id1'), 
    conditionalPanel(condition = "input['id1-select'] == 'Option one'", 
        p('Option one is selected.')) 
)) 

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

}) 

shinyApp(ui = ui, server = server) 

EDIT:

Tính năng này hoạt động nhưng không vi phạm khái niệm về mô đun? Bạn sẽ phải biết mã cho mô-đun nội bộ gọi là đầu vào 'chọn' để xây dựng 'id1-select'.

Có, bạn nói đúng.

Theo điều này article, mẹo bạn đã sử dụng tức là gán một cuộc gọi mô-đun cho đầu ra $ được chọn và sau đó truy cập giá trị của nó ở phía máy khách qua output.selected sẽ hoạt động nhưng không. Tôi không biết tại sao ... nó có thể là một lỗi. (Tôi có phiên bản bóng mới nhất từ ​​github)

Điều duy nhất tôi có thể nghĩ đến là sử dụng renderUI thay vì conditionalPanel như trong ví dụ dưới đây:

library(shiny) 
## Module code for 'selectorUI' and 'selector' 
selectorUI <- function(id) { 
    ns <- NS(id) 
    selectizeInput(inputId = ns('select'), 
       label = 'Make a choice:', 
       choices = c('Option one', 'Option two')) 
} 

selector <- function(input, output, session) { 
    reactive(input$select) 
} 

## Main app 
ui <- shinyUI(fluidPage(
    selectorUI('id1'), 
    uiOutput("dynamic1") 
)) 

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


    output$dynamic1 <- renderUI({ 
    condition1 <- callModule(selector, 'id1') # or just callModule(selector, 'id1')() 
    if (condition1() == 'Option one') return(p('Option one is selected.')) 
    }) 

}) 

shinyApp(ui = ui, server = server) 
+0

này làm việc, nhưng nó không vi phạm khái niệm về mô đun? Bạn sẽ phải biết mã cho mô-đun nội bộ gọi là đầu vào 'chọn' để xây dựng 'id1-select'. –

+0

Có, bạn nói đúng - tôi đã cập nhật bài đăng của mình. –

+1

Tôi nghĩ rằng đó thực sự là một lỗi. Tôi đã gửi nó với một ví dụ tối thiểu hơn tại https://github.com/rstudio/shiny/issues/1318. Tôi thích giải pháp 'renderUI' tốt hơn, bởi vì' conditionalPanel' dựa trên kiểu 'display: none' để ẩn nội dung, trong khi' renderUI' chỉ đưa ra một div trống. Cảm ơn bạn đã viết. –

2

Hóa ra nó thực sự không phải là một lỗi , chỉ cần một chút khéo léo. According to Joe Cheng,

Ngay - chúng tôi không, theo mặc định, tính toán/render giá trị sản lượng nếu họ sẽ không được hiển thị. Và nếu chúng ta không tính toán chúng, bạn không thể sử dụng chúng trong điều kiện.

Bạn có thể thay đổi hành vi này này bằng cách thiết lập một đầu ra để tính toán mọi thời gian, bạn có thể sử dụng trong server.R của bạn (thay thế outputId với giá trị tương ứng):

outputOptions(output, "outputId", suspendWhenHidden = FALSE)

Vì vậy, để sửa chữa vấn đề với ví dụ ban đầu của tôi, chúng ta chỉ cần thêm rằng một dòng vào các chức năng máy chủ:

server <- shinyServer(function(input, output, session) { 
    output$selected <- callModule(selector, 'id1') 
    outputOptions(output, 'selected', suspendWhenHidden = FALSE) # Adding this line 
}) 
Các vấn đề liên quan