GithubHelp home page GithubHelp logo

plotly / dashr Goto Github PK

View Code? Open in Web Editor NEW
381.0 27.0 34.0 63.7 MB

Create data science and AI web apps in R

Home Page: https://dashr.plotly.com

License: Other

R 13.53% Python 1.24% JavaScript 85.18% CSS 0.01% Dockerfile 0.04%
r dash react data-science data-visualization plotly python web-application plotly-dash

dashr's Introduction

R-CMD-check CRAN Status CRAN Downloads monthly

An R package for creating interactive web graphics via the open source JavaScript graphing library plotly.js.

Installation

Install from CRAN:

install.packages("plotly")

Or install the latest development version (on GitHub) via {remotes}:

remotes::install_github("plotly/plotly")

Getting started

Web-based ggplot2 graphics

If you use ggplot2, ggplotly() converts your static plots to an interactive web-based version!

library(plotly)
g <- ggplot(faithful, aes(x = eruptions, y = waiting)) +
  stat_density_2d(aes(fill = ..level..), geom = "polygon") + 
  xlim(1, 6) + ylim(40, 100)
ggplotly(g)

https://i.imgur.com/G1rSArP.gifv

By default, ggplotly() tries to replicate the static ggplot2 version exactly (before any interaction occurs), but sometimes you need greater control over the interactive behavior. The ggplotly() function itself has some convenient “high-level” arguments, such as dynamicTicks, which tells plotly.js to dynamically recompute axes, when appropriate. The style() function also comes in handy for modifying the underlying trace attributes (e.g. hoveron) used to generate the plot:

gg <- ggplotly(g, dynamicTicks = "y")
style(gg, hoveron = "points", hoverinfo = "x+y+text", hoverlabel = list(bgcolor = "white"))

https://i.imgur.com/qRvLgea.gifv

Moreover, since ggplotly() returns a plotly object, you can apply essentially any function from the R package on that object. Some useful ones include layout() (for customizing the layout), add_traces() (and its higher-level add_*() siblings, for example add_polygons(), for adding new traces/data), subplot() (for combining multiple plotly objects), and plotly_json() (for inspecting the underlying JSON sent to plotly.js).

The ggplotly() function will also respect some “unofficial” ggplot2 aesthetics, namely text (for customizing the tooltip), frame (for creating animations), and ids (for ensuring sensible smooth transitions).

Using plotly without ggplot2

The plot_ly() function provides a more direct interface to plotly.js so you can leverage more specialized chart types (e.g., parallel coordinates or maps) or even some visualization that the ggplot2 API won’t ever support (e.g., surface, mesh, trisurf, etc).

plot_ly(z = ~volcano, type = "surface")

https://plot.ly/~brnvg/1134

Learn more

To learn more about special features that the plotly R package provides (e.g., client-side linking, shiny integration, editing and generating static images, custom events in JavaScript, and more), see https://plotly-r.com. You may already be familiar with existing plotly documentation (e.g., https://plotly.com/r/), which is essentially a language-agnostic how-to guide for learning plotly.js, whereas https://plotly-r.com is meant to be more wholistic tutorial written by and for the R user. The package itself ships with a number of demos (list them by running demo(package = "plotly")) and shiny/rmarkdown examples (list them by running plotly_example("shiny") or plotly_example("rmd")). Carson also keeps numerous slide decks with useful examples and concepts.

Contributing

Please read through our contributing guidelines. Included are directions for opening issues, asking questions, contributing changes to plotly, and our code of conduct.

dashr's People

Contributors

alexcjohnson avatar byronz avatar chriddyp avatar cpsievert avatar daattali avatar dependabot[bot] avatar hammadtheone avatar jackparmer avatar jbampton avatar marc-andre-rivet avatar nicolaskruchten avatar rpkyle avatar tahirinadia avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dashr's Issues

Convert shiny.tag/shiny.tag.list objects to components?

It'd be cool if users could reuse their shiny UIs for a dash application, and more generally, insert shiny.tag/shiny.tag.list objects (from htmltools) inside their dash layout.

Since dash doesn't (yet) support arbitrary HTML, perhaps we could try to support a subset of these objects (i.e., everything but htmltools::HTML()), by translating each tag to a component.

As a side note, I wonder what shiny/htmltools does to prevent cross-side scripting (as discussed here)

Write a function to test get_package_mapping logic for security purposes

dashR currently uses a function to retrieve local paths to dependencies called get_package_mapping, which is critical for properly formatting response$body:

dashR/R/utils.R

Lines 394 to 425 in 7fa2581

get_package_mapping <- function(script_name, url_package, dependencies) {
# TODO: improve validation of dependency inputs, particularly
# to avoid duplicating dependencies in the package_map
package_map <- vapply(unique(dependencies), function(x) {
if (x$name %in% c('react', 'react-dom')) {
x$name <- 'dash-renderer'
}
dep_path <- paste(x$src$file,
x$script,
sep = "/")
# remove n>1 slashes and replace with / if present
result <- c(pkg_name=ifelse("package" %in% names(x), x$package, NULL),
dep_name=x$name,
dep_path=gsub("//+", replacement = "/", dep_path)
)
}, FUN.VALUE = character(3))
package_map <- t(package_map)
# pos_match is a vector of logical() values -- this allows filtering
# of the package_map entries based on name, path, and matching of
# URL package name against R package names. when all conditions are
# satisfied, pos_match will return TRUE
pos_match <- grepl(paste0(script_name, "$"), package_map[, "dep_path"]) &
grepl(url_package, package_map[,"dep_name"])
rpkg_name <- package_map[,"pkg_name"][pos_match]
rpkg_path <- package_map[,"dep_path"][pos_match]
return(list(rpkg_name=rpkg_name, rpkg_path=rpkg_path))
}

There are potential security issues associated with malicious users specifying arbitrary paths; we should be careful that URLs cannot be constructed such that the dep_pkg constructed from the URL is a non-Dash-related package.

We should write a function to test that get_package_mapping validates its input and attempts to block arbitrary code execution.

@chriddyp @alexcjohnson

Remove dashR dependency on htmltools

Given that we are aiming for parity with Dash for Python, and that "rolling our own" dependency handling/resolution logic is a minor hurdle, it seems prudent to eliminate references to code from htmltools in dashR.

Most of the references to functions in htmltools have been excised, with the exception of

dashR/R/dash.R

Line 554 in 7fa2581

depsAll <- htmltools::resolveDependencies(depsAll, FALSE)

#' @importFrom htmltools htmlDependency htmlDependencies attachDependencies renderDependencies

dashR/R/css.R

Line 33 in 7fa2581

htmltools::htmlDependency(

dashR/R/dash.R

Line 71 in 7fa2581

#' The `dependencies` argument accepts [htmltools::htmlDependency] or

dashR/R/dash.R

Line 361 in 7fa2581

stop("`dependencies` must be a *list* of htmltools::htmlDependency objects", call. = FALSE)

Aside from removing references to this package, I'll need to write a function which has the same effect as htmltools::resolveDependencies.

Provide support for external_stylesheets when initializing a DashR app

Dash for Python provides a simple, convenient method for app developers to insert URLs for external stylesheets into the page header. DashR currently lacks this functionality; implementing this requires accepting an external_stylesheets argument, which will be a list of URLs, as in Dash for Python:

https://github.com/plotly/dash/blob/e255ba0ff3ce5e3080b596ee04f9e5c902a07953/dash/dash.py#L97

Code should be written which iterates over this list and uses sprintf to prepare stylesheet tags, which we can then insert into the page header, as in Python:

https://github.com/plotly/dash/blob/e255ba0ff3ce5e3080b596ee04f9e5c902a07953/dash/dash.py#L418-L427

Finish and publish tutorials

We'll also want a few additional chapters that are dasher specific on https://plot.ly/dasher, including:

  • Routing plotly's plot_ly()/ggplotly() to dasher's coreGraph()
  • Leveraging wrapper functions (e.g., wrap_png() and wrap_print())
  • Leveraging htmlwidgets directly (assuming we can get this working)
  • Serving static files via fiery/routr and maybe other fiery specific things #3 (comment)

rmarkdown integration

It'd be neat to embed dashR apps inside rmarkdown (via runtime: dashR) similar to how one can embed shiny apps via runtime: shiny.

Allow options/marks to accept (named) vector/list

Similar to shiny::selectInput()'s choices argument, these should all be valid ways to specify options in a component like coreDropdown():

  • c("NYC", "LA")
  • c(NYC = "New York", LA = "Los Angeles")

Perhaps we could also support generic lists as well, but the intention isn't quite as well as we don't have a component that supports grouping like shiny does -- http://shiny.rstudio.com/gallery/option-groups-for-selectize-input.html

  • list("NYC", "LA")
  • list(NYC = "New York", LA = "Los Angeles")

The question here is, where should this logic (e.g., c("NYC", "LA") -> [{label: "NYC", value: "NYC"}, {label: "LA", value: "LA"}]) reside? I see two options:

  1. Since we already validate every input object (in dasher), we could add special "prop transform" handling where this makes sense.
  2. Put in the function signature for a particular component (dashTranspileR)...that would require, at the very least, argument naming to have consistent meaning throughout a component suite.

Refactor current approach to importing ggplotly and plot_ly objects in DashR

I had a very useful conversation with @alexcjohnson this afternoon, in which we discussed possible solutions to importing figure objects from plotly::plot_ly into DashR.

One pipeline for importing a figure produced by the plotly package looks like (thanks, @nicolaskruchten):

library(plotly)
p <- plot_ly(data = iris, x = ~Sepal.Length, y = ~Petal.Length)
plotly_figure <- plotly_build(p)$x

The resulting plotly_figure object then contains data and layout which should be suitable for dropping into dccGraph. Notably, the output of the plot_ly function includes an x$visdat field.

  • R's JSON formatter lacks hooks
    The challenge in DashR is that jsonlite::toJSON appears to offer no route to easily implementing hooks as json.dumps does in Python, so we cannot conditionally pre-process toJSON's input on the way to producing its stringified output.

  • "Walking and mutating"
    A temporary solution is to crawl the layout, recursing into any children of components, to identify properties which may contain x$visdat, and transform their contents using plotly_build prior to passing them along to jsonlite::toJSON.

Mutating the entire object before passing it to jsonlite::toJSON could be problematic if a DashR app is written such that global information about the layout is expected to be in its original, unmutated format. (A possible example involves a Dash app with tabs; @rpkyle will try to mock up a sample to demonstrate.)

  • Desired resolution
    This issue will be resolved when the approach (currently in development) to supporting plot_ly and ggplotly objects is refactored to use a walking and replacing (analogous to what currently happens in Dash for Python) approach in lieu of the walking and mutating strategy above.

@chriddyp

Make all exported objects camelCase

For better consistency with dash, I decided components should be camelCase (i.e., htmlDiv() versus html_div())

For better overall consistency, should probably use camelCase for dasher exports

Address bug in remote CSS dependency handling

#53 introduced a get_package_mapping function to construct a map matching keys$package from the _dash-component-suites handler to a (currently loaded) R package which supplies the dependency (if present).

While JavaScript dependency handling appears to work as intended, the update was not tested against remote CSS dependencies. This should be resolved before asset serving is implemented.

The crux of the issue is that get_package_mapping currently requires that four pieces of information are available:

  • a dependency name
  • the dependency "package" name from the URL (which is generally ≠ to the R package name)
  • a list of dependencies in htmltools format
  • the R package name, registered within each element of the dependency list described above

A PR (#57) has been proposed to handle this potential issue, by asserting that dependencies have valid name, URL package, and R package information before constructing the package map.

CRAN release strategy

Since CRAN won't let you import/suggest non-CRAN packages, these packages will have to be submitted first (might want to add a comment that these are useful by themselves, but will provide a foundation for downstream submissions):

https://github.com/plotly/dashTranspileR
https://github.com/plotly/dash-html-components
https://github.com/plotly/dash-core-components
https://github.com/plotly/dashHtmlwidgetComponent

Then these:

https://github.com/plotly/dash
https://github.com/plotly/dashAuthR

Asset serving

There's a surprisingly deep and complicated pipeline behind the generation of the component <script> tags that Dash drops into the index.html which it returns to clients on first load.

Minimally, DashR needs to serve script tags for locally served JS bundles that match the component libraries that are loaded in the initial layout.

This is on the critical path for #45

Address potential JS dependency loading issue for multipage DashR apps

@chriddyp raised an interesting weakness in the current dependency loading strategy for DashR (via calling the Python-generated JS metadata function (e.g. .dashHtmlComponents_js_metadata()).

In a multipage DashR app, it's possible that some dependencies may load properly for the first page, while any new components whose JS dependencies were not initially sourced may fail to load correctly.

There is a clever workaround in Dash for Python, but one does not currently exist in DashR.

I propose that we attempt the following strategy:

    1. Enumerate the installed packages which have an R package dependency on dashR
    1. Determine which of the dependent packages are currently attached (loaded)
    1. Check to see if the packages in (2) contain an internal JS metadata function, if so, tack its dependencies on to those already registered by DashR.

Here's an example to demonstrate what I'm proposing (.packages() invisibly returns the list, so it's printed here):

[1] "crosstalk"  "plotly"   
> print(.packages())
[1] "plotly"             "ggplot2"            "tools"              "dashRtutorial"      "magrittr"           "dashCoreComponents" "dashHtmlComponents"
[8] "dashR"              "stats"              "graphics"           "grDevices"          "utils"              "datasets"           "methods"           
[15] "base"  
> deps <- dependsOnPkgs("ggplot2")
> attached <- .packages()
> attached[attached %in% deps]
[1] "plotly"

I'm bumping this towards the top of the todo list because it could interfere with DashR docs.

@NadiaTahiri @T4rk1n

New app creation process

For Dash, setting up an empty repo to create a new app involves pip-installing 3 separate packages.

For parity, DashR should aim for something similar: 3 install-from-github calls (DashR, HTML and Core components). Because DashR itself will be a private repo for a little while, this will rely on the GITHUB_PAT environment variable being set, per https://www.rdocumentation.org/packages/devtools/versions/1.13.6/topics/install_github

This issue can be closed when the README for DashR documents this new process and it works :)

In addition, all of the examples and docs in this repo should work when the new installation process is used. They'll likely need to be adjusted to capture the removal of dependencies from DashR to HTML/Core components, and then QA'ed to ensure that they all work using the latest version of the components.

Depends on plotly/dash-html-components#74 and plotly/dash-core-components#357

Test first draft of dashR examples

Examples available to test

  • 'basic-callbacks-example-1.R'
  • 'basic-callbacks-example-2.R'
  • 'basic-callbacks-state.R'
  • 'basic-input.R'
  • 'basic-input2.R'
  • 'basic-state.R' (no error, not sure of the result, we need to debug more)
  • 'callback-png-slider.R' (Rstudio errors: 1) line by line, Error: attempt to apply non-function and 2) all script by runTutorial(...), Error in eval(ei, envir) : attempt to apply non-function)
  • 'callback-png-slider2.R' See below (same errors that 'callback-png-slider.R' )
  • 'callbacks-with-dependencies.R' (with WARNING message: error: invalid subscript type 'list') To check?
  • 'core_components/button.R' (see changt of list (first time to character otherwise?)
  • 'core_components/date-picker-range.R' (note to install.packages("lubridate"))
  • 'core_components/date-picker-single.R'
  • 'core_components/dropdown.R'
  • 'core_components/rangeslider-nonlinear.R'
  • 'core_components/rangeslider.R'
  • 'core_components/slider-marks.R'
  • 'core_components/slider.R'
  • 'core_components/upload-datafile.R' (Error in loadNamespace(name) : there is no package called ‘dashTable’)
  • 'core_components/upload-gallery.R' (Error: dash_html_components was not found.) (Maybe dashTable?)
  • 'core_components/upload-image.R' (to confirm)
  • 'crossfilter-recipe.R' (to debugg)
  • 'download-csv.R' (note to install.packages("readr"))
  • 'dynamic-content.R' (# essentially the same as ./basic-state.R)
  • 'excel.R'
  • 'getting-started-callback-chain.R' (empty file same that # essentially the same as ./callbacks-with-dependencies.R)
  • 'getting-started-core-components.R' (Error loading dependencies)
    bundle.js:2 Error: dash_html_components was not found. at Object.resolve (bundle.js:14) at s (bundle.js:14) at Array.map (<anonymous>) at s (bundle.js:14) at Array.map (<anonymous>) at s (bundle.js:14) at e.value (bundle.js:14) at p._renderValidatedComponentWithoutOwnerOrContext (react-dom.min.js:13) at p._renderValidatedComponent (react-dom.min.js:13) at performInitialMount (react-dom.min.js:13)
  • 'getting-started-crossfilter.R' (no error, not sure of the result, we need to debug more)
  • 'getting-started-layout-1.R' (Error loading dependencies)
    bundle.js:2 Error: dash_html_components was not found. at Object.resolve (bundle.js:14) at s (bundle.js:14) at Array.map (<anonymous>) at s (bundle.js:14) at e.value (bundle.js:14) at p._renderValidatedComponentWithoutOwnerOrContext (react-dom.min.js:13) at p._renderValidatedComponent (react-dom.min.js:13) at performInitialMount (react-dom.min.js:13) at p.mountComponent (react-dom.min.js:13) at Object.mountComponent (react-dom.min.js:14)
  • 'getting-started-layout-2.R' (Error loading dependencies)
    bundle.js:2 Error: dash_html_components was not found. at Object.resolve (bundle.js:14) at s (bundle.js:14) at Array.map (<anonymous>) at s (bundle.js:14) at Array.map (<anonymous>) at s (bundle.js:14) at e.value (bundle.js:14) at p._renderValidatedComponentWithoutOwnerOrContext (react-dom.min.js:13) at p._renderValidatedComponent (react-dom.min.js:13) at performInitialMount (react-dom.min.js:13) (anonymous) @ bundle.js:2
  • 'getting-started-markdown.R' (Error loading dependencies)
    bundle.js:2 Error: dash_core_components was not found. at Object.resolve (bundle.js:14) at s (bundle.js:14) at Array.map (<anonymous>) at s (bundle.js:14) at e.value (bundle.js:14) at p._renderValidatedComponentWithoutOwnerOrContext (react-dom.min.js:13) at p._renderValidatedComponent (react-dom.min.js:13) at performInitialMount (react-dom.min.js:13) at p.mountComponent (react-dom.min.js:13) at Object.mountComponent (react-dom.min.js:14)
  • 'getting-started-part-2-callback-chain.R'
  • 'getting-started-part-2-graph.R'
  • 'getting-started-part-2-interactive-simple.R'
  • 'getting-started-part-2-multiple-outputs-1.R'
  • 'getting-started-part-2-multiple-viz.R' (Error loading dependencies)
    bundle.js:2 TypeError: undefined does not have a method named "concat" at bundle.js:2 at e (bundle.js:1) at bundle.js:1 at Array.map (<anonymous>) at l (bundle.js:1) at bundle.js:1 at bundle.js:28 at dispatch (bundle.js:28) at bundle.js:1 at Array.forEach (<anonymous>)
  • 'getting-started-table.R' (Error loading dependencies)
    bundle.js:2 Error: dash_html_components was not found. at Object.resolve (bundle.js:14) at s (bundle.js:14) at Array.map (<anonymous>) at s (bundle.js:14) at e.value (bundle.js:14) at p._renderValidatedComponentWithoutOwnerOrContext (react-dom.min.js:13) at p._renderValidatedComponent (react-dom.min.js:13) at performInitialMount (react-dom.min.js:13) at p.mountComponent (react-dom.min.js:13) at Object.mountComponent (react-dom.min.js:14)
  • 'getting-started-viz.R' (Error loading dependencies)
    bundle.js:2 Error: dash_core_components was not found. at Object.resolve (bundle.js:14) at s (bundle.js:14) at Array.map (<anonymous>) at s (bundle.js:14) at e.value (bundle.js:14) at p._renderValidatedComponentWithoutOwnerOrContext (react-dom.min.js:13) at p._renderValidatedComponent (react-dom.min.js:13) at performInitialMount (react-dom.min.js:13) at p.mountComponent (react-dom.min.js:13) at Object.mountComponent (react-dom.min.js:14)
  • 'getting-started.R' (empty file, same example # essentially the same as ./basic-callbacks-example-1.R)
  • 'graph-callbacks-crossfiltering.R'
  • 'graph-callbacks-same-graph.R'
  • 'graph-callbacks-simple.R' (Error in eval(ei, envir) : attempt to apply non-function)
  • 'layout-dynamic.R' (Error loading dependencies)
    Error: dash_html_components was not found. at Object.resolve (bundle.js:14) at s (bundle.js:14) at Array.map (<anonymous>) at s (bundle.js:14) at e.value (bundle.js:14) at p._renderValidatedComponentWithoutOwnerOrContext (react-dom.min.js:13) at p._renderValidatedComponent (react-dom.min.js:13) at performInitialMount (react-dom.min.js:13) at p.mountComponent (react-dom.min.js:13) at Object.mountComponent (react-dom.min.js:14) (anonymous) @ bundle.js:2
  • 'live-updates-tour.R' (need install.packages("tourr")), browser, (no error, not sure of the result, we need to debug more)
  • 'live-updates.R'
  • 'multi-page-app/app.R' (Error loading dependencies)
    bundle.js:2 Error: dash_html_components was not found. at Object.resolve (bundle.js:14) at s (bundle.js:14) at Array.map (<anonymous>) at s (bundle.js:14) at Array.map (<anonymous>) at s (bundle.js:14) at e.value (bundle.js:14) at p._renderValidatedComponentWithoutOwnerOrContext (react-dom.min.js:13) at p._renderValidatedComponent (react-dom.min.js:13) at performInitialMount (react-dom.min.js:13)
  • 'multi-page-app/apps/app1.R'
    Error in modules::import_("app", attach = "app") : Unable to load module ‘app’; not found in ‘/Library/Frameworks/R.framework/Versions/3.5/Resources/library/dashR/tutorial/examples/multi-page-app/apps’
  • 'multi-page-app/apps/app2.R'
    Error in modules::import_("app", attach = "app") : Unable to load module ‘app’; not found in ‘/Library/Frameworks/R.framework/Versions/3.5/Resources/library/dashR/tutorial/examples/multi-page-app/apps’
  • 'multi-page-app/index.R'
    Attaching package: "modules" The following objects are masked from "package:utils": ?, help Fire started at 127.0.0.1:8080
    error: Couldn't find output component. Please let us know about this error via https://github.com/plotly/dashR/issues/new
  • 'performance-caching-dataset.R'
    Error in as.character(function (seconds, current = as.numeric(Sys.time())) : cannot coerce type 'closure' to vector of type 'character'
  • 'performance-caching.R'
    TODO: how does memoise::timeout() work??? => library(memoise)
    Error in cache_redis() : could not find function "cache_redis"
  • 'performance-memoization.R' (empty file?)
  • 'style-custom.R' (Error loading dependencies)
    bundle.js:2 Error: dash_html_components was not found. at Object.resolve (bundle.js:14) at s (bundle.js:14) at Array.map (<anonymous>) at s (bundle.js:14) at Array.map (<anonymous>) at s (bundle.js:14) at e.value (bundle.js:14) at p._renderValidatedComponentWithoutOwnerOrContext (react-dom.min.js:13) at p._renderValidatedComponent (react-dom.min.js:13) at performInitialMount (react-dom.min.js:13)
  • 'style-dash-css.R' (Error loading dependencies)
    bundle.js:2 Error: dash_core_components was not found. at Object.resolve (bundle.js:14) at s (bundle.js:14) at Array.map (<anonymous>) at s (bundle.js:14) at e.value (bundle.js:14) at p._renderValidatedComponentWithoutOwnerOrContext (react-dom.min.js:13) at p._renderValidatedComponent (react-dom.min.js:13) at performInitialMount (react-dom.min.js:13) at p.mountComponent (react-dom.min.js:13) at Object.mountComponent (react-dom.min.js:14) (anonymous) @ bundle.js:2
  • 'style-link.R'
  • 'style-unpkg.R' (Error in library(runpkg) : there is no package called ‘runpkg’)
  • 'toggle-display.R'
  • 'urls-part-2.R'
  • 'urls.R'
  • 'walmart.R'

callbacks with no inputs may not return a value

Could have something to do with the way callbacks are evaluated

library(dasher)
library(plotly)

app <- Dash$new()

app$layout_set(
  Htmlwidget(id = 'plotID', name = "plotly"),
  htmlDiv(id = 'event')
)

app$callback(
  function() {
    plot_ly(mtcars, x = ~wt, y = ~mpg)
  },
  output(id = 'plotID', property = "payload")
)

app$callback(
  function(inputs = input("plotID", property = "ctSelection")) {
    inputs
  },
  output(id = 'event')
)

# plotly has 'run-time' dependencies that must be registered before
# the application is launched. For other htmlwidgets, this may not
# be necessary.
app$dependencies_set(plot_ly()$dependencies)
app$run_server()

Master list of Flask features we're missing

Similar to dash, dasher takes a fiery (flask) server as input to the initialization method, and also exposes (modified version of) that server as a field, for example:

import flask
import dash

server = flask.Flask(__name__)
app = dash.Dash(__name__, server=server)
app.server # the flask server
library(fiery)
library(dasher)

server <- Fire$new()
app <- Dash$new(server = server)
app$server # the fiery server

This allows folks to add/customize functionality of the underlying web server, which is great, but is bound to lead to scenarios where something is possible/easy in flask, but isn't (yet) easy-to-do via fiery. This comment/issue serves as a 'master list' of those (currently known) features (which I'm hoping will help us organize/delegate/motivate @thomasp85 into implementing more fiery methods/plug-ins):

Testing

My plan is to test locally before launch, then use TravisCI once launched

Better app print method

For example

library(dasher)

app <- Dash$new()

app$layout_set(
  coreInput(id = 'input-1', value = 'Montréal', type = "text"),
  coreInput(id = 'input-2', value = 'Canada', type = "text"),
  htmlDiv(id = 'output')
)

app$callback(
  function(x = input("input-1"), y = input("input-2")) {
    sprintf("Input 1 is '%s' and input 2 is '%s'", x, y)
  },
  output("output")
)

app$dependencies_set(dash_css())
app

Should print something like this (maybe leverage crayon to add formatting)

#> A dasher webserver
#>  📈  📊  📈
#>  * __layout__
#>       * core components:
#>          * Input: 2
#>       * html components:
#>          * Div: 1  
#>
#>   * __callbacks__
#>       * inputs:
#>           * input-1.value
#>           * input-2.value     
#>        * output
#>           * output.children
#>
#>  * __dependencies__
#>       * dash-css

Fix 500s on initial session launch

Sometimes (seems to be random) the servers errors out with 500s when the client requests JS/CSS dependencies...need to refresh the browser to fix at the moment

Make it easier to use css "themes"

For starters, make a helper to leverage @chriddyp's recommended CSS

css <- function() {
  htmltools::htmlDependency(
    name = "dash-css",
    version = "1.0.0",
    src = c(href = "https://codepen.io/chriddyp/pen"),
    stylesheet = "bWLwgP.css"
  )
}

Then you could something like:

app$dependencies_set(css())

Responding to (plotly htmlwidget) plotly.js events

The Graph() component achieves this via hoverData/clickData/etc props, but Htmlwidget() is meant to be generic, so something like this won't necessarily scale or be idiomatic.

I'm thinking this could/should be done via a new component (maybe named dashPlotlyEvents::PlotlyEvent()) that works a lot like https://github.com/plotly/dashCrosstalkComponent (that is, the id of the component is used to query the relevant target, and the other props manage the event data)

Tools for debugging components

It's hard to know when/why a component is 'mis-specified'. Furthermore, my current debugging process is not ideal (app$layout_set(component); app$layout_get(); app$run_server()). Some ideas for improvements:

  1. Printing a component could spin up a simple dash app with just that component.
  2. Provide a 'debugging mode/option' where client side errors are listed in a pop-up (the current generic Error loading dependencies message is not helpful and most folks won't know to open their browser's dev tools)
  3. Automatically type check arguments in R using the components propTypes definition

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.