Replies: 5 comments 4 replies
-
FieldsI don't think fields need to be implemented as modules. We might need a hook to be able to register some observables (i.e. for ace editor or for file browser fields), but communication with the user happens exclusively via An (optional) server function for fields was added in #146, but I'm planning on reverting this change medium term. Can be further discussed. A question to be answered before doing this is how well we feel that "compound" fields behave. |
Beta Was this translation helpful? Give feedback.
-
BlocksThe block server function instantiates a reactive representation of the block object which reacts to relevant changes in
Further tasks/actions of the block server function include the following:
|
Beta Was this translation helpful? Give feedback.
-
Stacks (WIP)The stack server function (as for the block) creates a reactive representation of the stack which is updated if
It has available the return values of the corresponding block server modules, i.e. reactive representations of blocks and output data. |
Beta Was this translation helpful? Give feedback.
-
Workspace (WIP)Currently implemented as singleton object, the workspace also (unlike other objects) comes with reference semantics (implemented as environment). |
Beta Was this translation helpful? Give feedback.
-
I am currently testing some possible simplifications of the plot server methods. Below is a WIP test for a dataset block, without the stack wrapper. The core "experiment" here is the creation of 1 observer per field so that each time the related input change, we only update this field. That works well for a simple block like this, I did not check yet how to handle dynamic fields like with the filter block. generate_server.dataset_block <- function(x, id, ...) {
moduleServer(
id,
function(input, output, session) {
ns <- session$ns
blk <- reactiveVal(x)
obs <- list()
is_valid <- reactiveValues(block = FALSE)
# For each block field, we listen to its related input
# so that we can update the block accordingly and keep shiny/blockr in sync
# I don't call update_fields but update_field as I listen to each field individually
# which avoids to update the block when not necessary. The benefit is to avoid
# triggering unecessary reactive issues.
lapply(names(x), \(field) {
# Don't process hidden fields (as they correspond to no shiny input)
if (!inherits(x[[field]], "hidden_field")) {
obs[[sprintf("update_%s_field", field)]] <- observeEvent(input[[field]], {
tmp <- blk()
tmp[[field]] <- update_field(tmp[[field]], input[[field]], list())
blk(tmp)
is_valid$block <- validate_block(blk())
})
}
})
out_dat <- reactive({
validate(need(is_valid$block, "Block is not valid"))
evaluate_block(blk())
})
output$res <- renderTable(out_dat())
return(
list(
block = blk,
data = out_dat,
# Needed by the stack to block
# computations for the next block
is_valid = reactive(is_valid$block)
)
)
}
)
}
# Minimal block UI for testing
generate_ui.dataset_block <- function(x, id, ...) {
ns <- shiny::NS(id)
tagList(
ui_fields(x, ns, ""),
tableOutput(ns("res"))
)
}
library(shiny)
library(bslib)
blk <- initialize_block(new_dataset_block())
shinyApp(
ui = page_fluid(
generate_ui(blk, "test")
),
server = function(input, output, session) {
plop <- generate_server(blk, "test")
observe(print(plop$data()))
}
) |
Beta Was this translation helpful? Give feedback.
-
This discussion topic should clarify what the server modules for fields, blocks, stacks and the workspace do, expect as inputs and produce as outputs. I will start with 4 separate posts on each of the object types.
Beta Was this translation helpful? Give feedback.
All reactions