Skip to content

Commit edbcc04

Browse files
rpkyleHammadTheOne
and
HammadTheOne
authored
Dash for R v0.9.0 (#239)
* Fix setCallbackContext for wildcard and ordinary inputs (#237) * Update dash-renderer to v1.8.3 Co-authored-by: HammadTheOne <[email protected]>
1 parent add8dd3 commit edbcc04

9 files changed

+167
-24
lines changed

CHANGELOG.md

+12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,18 @@
22
All notable changes to `dash` will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/).
44

5+
## [0.9.0] - 2020-10-31
6+
7+
### Fixed
8+
- Fixes a minor bug in `setCallbackContext` (described in [#236](https://github.com/plotly/dashR/issues/236)) which prevented pattern-matching callbacks from working properly if one or more `input` statements did not include a selector. [#237](https://github.com/plotly/dashR/pull/237)
9+
10+
### Changed
11+
12+
- Dash for R now depends on v1.1.1 of `dashHtmlComponents`
13+
- Dash for R now depends on v1.13.0 of `dashCoreComponents`
14+
- Dash for R now depends on v4.11.0 of `dashTable`
15+
- `dash-renderer` version is now v1.8.3
16+
517
## [0.8.0] - 2020-10-27
618
### Fixed
719
- Usage of `glue` has been corrected to address [#232](https://github.com/plotly/dashR/issues/232) via [#233](https://github.com/plotly/dashR/pull/233).

DESCRIPTION

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
Package: dash
22
Title: An Interface to the Dash Ecosystem for Authoring Reactive Web Applications
3-
Version: 0.8.0
3+
Version: 0.9.0
44
Authors@R: c(person("Chris", "Parmer", role = c("aut"), email = "[email protected]"), person("Ryan Patrick", "Kyle", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-5829-9867"), email = "[email protected]"), person("Carson", "Sievert", role = c("aut"), comment = c(ORCID = "0000-0002-4958-2844")), person("Hammad", "Khan", role = c("aut"), comment = c(ORCID = "0000-0003-2479-9841"), email = "[email protected]"), person(family = "Plotly Technologies", role = "cph"))
55
Description: A framework for building analytical web applications, Dash offers a pleasant and productive development experience. No JavaScript required.
66
Depends:
77
R (>= 3.0.2)
88
Imports:
9-
dashHtmlComponents (== 1.0.3),
10-
dashCoreComponents (== 1.10.2),
11-
dashTable (== 4.9.0),
9+
dashHtmlComponents (== 1.1.1),
10+
dashCoreComponents (== 1.13.0),
11+
dashTable (== 4.11.0),
1212
R6,
1313
fiery (> 1.0.0),
1414
routr (> 0.2.0),
@@ -33,9 +33,9 @@ Collate:
3333
'imports.R'
3434
'print.R'
3535
'internal.R'
36-
Remotes: plotly/dash-html-components@e63acfa,
37-
plotly/dash-core-components@0770afb,
38-
plotly/dash-table@75ac3d9
36+
Remotes: plotly/dash-html-components@7209e0a,
37+
plotly/dash-core-components@91a424e,
38+
plotly/dash-table@aa519b7
3939
License: MIT + file LICENSE
4040
Encoding: UTF-8
4141
LazyData: true

R/internal.R

+12-12
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@
3636
all_files = FALSE),
3737
class = "html_dependency"),
3838
`dash-renderer-dev` = structure(list(name = "dash-renderer",
39-
version = "1.8.2",
40-
src = list(href = "https://unpkg.com/[email protected].2",
41-
file = "lib/[email protected].2"),
39+
version = "1.8.3",
40+
src = list(href = "https://unpkg.com/[email protected].3",
41+
file = "lib/[email protected].3"),
4242
meta = NULL,
4343
script = "dash-renderer/dash_renderer.dev.js",
4444
stylesheet = NULL,
@@ -48,9 +48,9 @@
4848
all_files = FALSE),
4949
class = "html_dependency"),
5050
`dash-renderer-map-dev` = structure(list(name = "dash-renderer",
51-
version = "1.8.2",
52-
src = list(href = "https://unpkg.com/[email protected].2",
53-
file = "lib/[email protected].2"),
51+
version = "1.8.3",
52+
src = list(href = "https://unpkg.com/[email protected].3",
53+
file = "lib/[email protected].3"),
5454
meta = NULL,
5555
script = "dash-renderer/dash_renderer.dev.js.map",
5656
stylesheet = NULL,
@@ -60,9 +60,9 @@
6060
all_files = FALSE),
6161
class = "html_dependency"),
6262
`dash-renderer-prod` = structure(list(name = "dash-renderer",
63-
version = "1.8.2",
64-
src = list(href = "https://unpkg.com/[email protected].2",
65-
file = "lib/[email protected].2"),
63+
version = "1.8.3",
64+
src = list(href = "https://unpkg.com/[email protected].3",
65+
file = "lib/[email protected].3"),
6666
meta = NULL,
6767
script = "dash-renderer/dash_renderer.min.js",
6868
stylesheet = NULL,
@@ -72,9 +72,9 @@
7272
all_files = FALSE),
7373
class = "html_dependency"),
7474
`dash-renderer-map-prod` = structure(list(name = "dash-renderer",
75-
version = "1.8.2",
76-
src = list(href = "https://unpkg.com/[email protected].2",
77-
file = "lib/[email protected].2"),
75+
version = "1.8.3",
76+
src = list(href = "https://unpkg.com/[email protected].3",
77+
file = "lib/[email protected].3"),
7878
meta = NULL,
7979
script = "dash-renderer/dash_renderer.min.js.map",
8080
stylesheet = NULL,

R/utils.R

+9-5
Original file line numberDiff line numberDiff line change
@@ -1054,26 +1054,30 @@ setCallbackContext <- function(callback_elements) {
10541054
function(x) {
10551055
input_id <- splitIdProp(x)[1]
10561056
prop <- splitIdProp(x)[2]
1057-
1057+
10581058
# The following conditionals check whether the callback is a pattern-matching callback and if it has been triggered.
10591059
if (startsWith(input_id, "{")){
10601060
id_match <- vapply(callback_elements$inputs, function(x) {
10611061
x <- unlist(x)
10621062
any(x[grepl("id.", names(x))] %in% jsonlite::fromJSON(input_id)[[1]])
10631063
}, logical(1))[[1]]
10641064
} else {
1065-
id_match <- vapply(callback_elements$inputs, function(x) x$id %in% input_id, logical(1))
1065+
id_match <- vapply(callback_elements$inputs, function(x) {
1066+
unlist(x)
1067+
any(x$id %in% input_id)}, logical(1))
10661068
}
1067-
1069+
10681070
if (startsWith(input_id, "{")){
10691071
prop_match <- vapply(callback_elements$inputs, function(x) {
10701072
x <- unlist(x)
10711073
any(x[names(x) == "property"] %in% prop)
10721074
}, logical(1))[[1]]
10731075
} else {
1074-
prop_match <- vapply(callback_elements$inputs, function(x) x$property %in% prop, logical(1))
1076+
prop_match <- vapply(callback_elements$inputs, function(x) {
1077+
unlist(x)
1078+
any(x$property %in% prop)}, logical(1))
10751079
}
1076-
1080+
10771081
if (startsWith(input_id, "{")){
10781082
if (length(callback_elements$inputs) == 1 || !is.null(unlist(callback_elements$inputs, recursive = F)$value)) {
10791083
value <- sapply(callback_elements$inputs[id_match & prop_match], `[[`, "value")

tests/integration/callbacks/test_pattern_matching.py

+127
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,120 @@
318318
"""
319319

320320

321+
graphs_app = """
322+
library(dash)
323+
library(dashHtmlComponents)
324+
library(dashCoreComponents)
325+
library(plotly)
326+
327+
df <- read.csv(
328+
file = "https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv",
329+
stringsAsFactor=FALSE,
330+
check.names=FALSE
331+
)
332+
333+
app <- Dash$new()
334+
335+
app$layout(
336+
htmlDiv(
337+
list(
338+
htmlDiv(
339+
list(
340+
dccDropdown(options = lapply(unique(df[,"country"]), function(x) {
341+
list(label = x, value = x)
342+
}),
343+
value = "Canada",
344+
id = "country",
345+
style = list(display = "inline-block",
346+
width = 200)
347+
),
348+
htmlButton(
349+
"add Chart",
350+
id = "add-chart",
351+
n_clicks = 0,
352+
style = list(display = "inline-block")
353+
)
354+
)
355+
),
356+
htmlDiv(id = "container", children=list()),
357+
htmlDiv(id = "output-delay")
358+
)
359+
)
360+
)
361+
362+
create_figure <- function(df, column_x, column_y, country) {
363+
df <- df[which(df[, "country"] == country),]
364+
if (column_x == "year") {
365+
fig <- plot_ly(df, x = df[,column_x], y = df[,column_y], name = column_x, type = "scatter", mode = "lines")
366+
} else {
367+
fig <- plot_ly(df, x = df[,column_x], y = df[,column_y], name = column_x, type = "scatter", mode = "markers")
368+
}
369+
fig <- plotly::layout(fig, plot_bgcolor="lightblue", xaxis = list(title=""),
370+
yaxis = list(title=""), title=list(text=paste(country, column_y, "vs", column_x),
371+
xanchor="right", margin_l=10, margin_r=0, margin_b=30))
372+
return(fig)
373+
}
374+
375+
app$callback(
376+
output = list(
377+
output(id = "container", property = "children"),
378+
output(id = "output-delay", property = "children")
379+
),
380+
params = list(
381+
input(id = "add-chart", property = "n_clicks"),
382+
state(id = "country", property = "value"),
383+
state(id = "container", property = "children")
384+
),
385+
function(n_clicks, country, children) {
386+
default_column_x <- "year"
387+
default_column_y <- "gdpPercap"
388+
389+
new_element <- htmlDiv(
390+
style = list(width = "23%", display = "inline-block", outline = "thin lightgrey solid", padding = 10),
391+
children = list(
392+
dccGraph(
393+
id = list(type = "dynamic-output", index = n_clicks),
394+
style = list(height = 300),
395+
figure = create_figure(df, default_column_x, default_column_y, country)
396+
),
397+
dccDropdown(
398+
id = list(type = "dynamic-dropdown-x", index = n_clicks),
399+
options = lapply(colnames(df), function(x) {
400+
list(label = x, value = x)
401+
}),
402+
value = default_column_x
403+
),
404+
dccDropdown(
405+
id = list(type = "dynamic-dropdown-y", index = n_clicks),
406+
options = lapply(colnames(df), function(x) {
407+
list(label = x, value = x)
408+
}),
409+
value = default_column_y
410+
)
411+
)
412+
)
413+
414+
children <- c(children, list(new_element))
415+
return(list(children, n_clicks))
416+
}
417+
)
418+
419+
app$callback(
420+
output(id = list("index" = MATCH, "type" = "dynamic-output"), property = "figure"),
421+
params = list(
422+
input(id = list("index" = MATCH, "type" = "dynamic-dropdown-x"), property = "value"),
423+
input(id = list("index" = MATCH, "type" = "dynamic-dropdown-y"), property = "value"),
424+
input(id = "country", property = "value")
425+
),
426+
function(column_x, column_y, country) {
427+
return(create_figure(df, column_x, column_y, country))
428+
}
429+
)
430+
431+
app$run_server()
432+
"""
433+
434+
321435
def test_rpmc001_pattern_matching_all(dashr):
322436
dashr.start_server(all_app)
323437
dashr.find_element("#add-filter").click()
@@ -370,3 +484,16 @@ def test_rpmc004_pattern_matching_todo(dashr):
370484
dashr.find_element("#add").click()
371485
dashr.find_element('#\\{\\"index\\"\\:1\\,\\"type\\"\\:\\"done\\"\\}').click()
372486
assert dashr.wait_for_text_to_equal("#totals", "1 of 1 items completed - 100%")
487+
488+
489+
def test_rpmc005_pattern_matching_graphs(dashr):
490+
dashr.start_server(graphs_app)
491+
dashr.select_dcc_dropdown("#country", "Cameroon")
492+
dashr.wait_for_text_to_equal("#output-delay", "0")
493+
dashr.find_element("#add-chart").click()
494+
dashr.wait_for_text_to_equal("#output-delay", "1")
495+
dashr.find_element('#\\{\\"index\\"\\:1\\,\\"type\\"\\:\\"dynamic-output\\"\\}')
496+
dashr.select_dcc_dropdown('#\\{\\"index\\"\\:1\\,\\"type\\"\\:\\"dynamic-dropdown-x\\"\\}', "year")
497+
dashr.select_dcc_dropdown('#\\{\\"index\\"\\:1\\,\\"type\\"\\:\\"dynamic-dropdown-y\\"\\}', "pop")
498+
dashr.percy_snapshot("r-pmc-graphs")
499+
dashr.wait_for_element('#\\{\\"index\\"\\:1\\,\\"type\\"\\:\\"dynamic-output\\"\\}')

0 commit comments

Comments
 (0)