-
-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reduce unwanted reactivity on filter panel changes #593
Conversation
Looks good already. |
Yu, I just noticed that when What if you try to bind on a call here? |
Unit Tests Summary 1 files 29 suites 22s ⏱️ For more details on these failures, see this check. Results for commit 3ab89db. ♻️ This comment has been updated with latest results. |
R/FilteredDataset.R
Outdated
@@ -42,6 +42,11 @@ FilteredDataset <- R6::R6Class( # nolint | |||
private$dataname <- dataname | |||
private$keys <- keys | |||
private$label <- if (is.null(label)) character(0) else label | |||
private$reactive_call <- reactiveVal() | |||
|
|||
observeEvent(self$get_call(), ignoreNULL = FALSE, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is constructor - it should be outside of a reactive context. It is only because srv_teal
insertUI
which is wrong and will be removed sooner or later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reverted that change 👍🏽
I was surprised that observing outside a module server worked just fine. Right now the observer is inside the srv_active
which is also not correct. It should be somewhere similar to the global server init. I will try to move this to some server logic in the FilterData
class.
But, this adds a new problem. The dataset is only dependant on the private$reactive_call ()
which needs shiny to work. So, we have some unit tests failing. As, those tests used to be reactive on the self$get_call()
before.
This reverts commit 4c4b081.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filter-counts are broken
@@ -53,7 +54,7 @@ FilteredDataset <- R6::R6Class( # nolint | |||
} | |||
env <- new.env(parent = parent.env(globalenv())) | |||
env[[dataname]] <- private$dataset | |||
filter_call <- self$get_call(sid) | |||
filter_call <- private$reactive_call() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It won't work for filter-counts which has non-empty sid
as an argument. Let me explain briefly how sid
works and why you can't cache these object in FilteredDataset
.
For given FilterState(s)
configuration there are two kind of calls (and data) produced in the same time. When the filter is modified possibly multiple calls of data_filtered_fun
are invoked. This means that this can't be cached here because this function needs to be called several times with different sid
.
- All FilterState are combined into one call and it is returned to the module. For this case your current solution works just perfect
- reactive counts in a single (each) FilterState are calculated on data filtered by every filter but not "this" filter.
Why are counts so weird?
When you filter single column you'd like to still see the counts of the unfiltered ranges. If we don't show these counts user wouldn't know how many observations are outside of the filtered range.
correct | incorrect |
---|---|
Even more technical explaination here
example app
# options(teal.log_level = "TRACE", teal.show_js_log = TRUE)
library("teal.slice")
library(teal)
library(scda)
library(SummarizedExperiment)
data <- teal_data() |> within({
# MAE <- hermes::multi_assay_experiment
ADSL <- synthetic_cdisc_data("latest")$adsl
ADSL$empty <- NA
ADSL$logical1 <- FALSE
ADSL$logical <- sample(c(TRUE, FALSE), size = nrow(ADSL), replace = TRUE)
ADSL$numeric <- rnorm(nrow(ADSL))
ADSL$categorical <- sample(letters[1:10], size = nrow(ADSL), replace = TRUE)
ADSL$date <- Sys.Date() + seq_len(nrow(ADSL))
ADSL$datetime <- Sys.time() + seq_len(nrow(ADSL)) * 3600 * 12
ADSL$numeric[sample(1:nrow(ADSL), size = 10, )] <- NA
ADSL$numeric[sample(1:nrow(ADSL), size = 10, )] <- Inf
ADSL$logical[sample(1:nrow(ADSL), size = 10, )] <- NA
ADSL$date[sample(1:nrow(ADSL), size = 10, )] <- NA
ADSL$datetime[sample(1:nrow(ADSL), size = 10, )] <- NA
ADSL$categorical[sample(1:nrow(ADSL), size = 10, )] <- NA
ADTTE <- synthetic_cdisc_data("latest")$adtte
ADRS <- synthetic_cdisc_data("latest")$adrs
})
teal.data::datanames(data) <- c(
# "MAE",
"ADSL", "ADTTE", "ADRS"
)
teal.data::join_keys(data) <- teal.data::default_cdisc_join_keys[teal.data::datanames(data)]
app <- init(
data = data,
modules = list(
example_module("mod1"),
modules(
example_module("mod2")
)
),
filter = teal_slices(
teal_slice("ADSL", "numeric", id = "numeric1"),
teal_slice("ADSL", "numeric", id = "numeric2"),
module_specific = TRUE,
mapping = list(
mod1 = "numeric1",
mod2 = "numeric2"
),
count_type = "all"
)
)
runApp(app)
Closes #62
Pending things before it can be undrafted:
private$reactive_call
for a givensid
. Right now it will not work whensid
is provided. A possible solution is to make thesid
a private object and use it inside the server logic.self$get_call()
to extract the call.data.frame
.CDISC
data.frame
andMAE
object.Example app to test: