knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

This vignette provides you with all information you need to create your first explorer tree and add it to your Shiny app. We will deal with R6-Classes, so some basic understanding as provided by the introduction vignette of the R6 package might be helpful, but is not mandatory. shinyExplorer exports three core R6-classes: ExplorerTree, ExplorerNode and ExplorerClass. For convenience we will denote objects of these classes with lower letter abbreviations, i.e. tree, node and explorer_class.

Since the classes implement some methods showing reactive behaviour, we need to call shiny::isolate, if using them without a reactive context. Inside your app's server function, of course, you don't need to do this. Throughout this vignette, we avoid using it by not evaluating the code chunks.

Create a new tree

We begin by creating a new tree:

explorer_tree <- ExplorerTree$new(
  root_id = "root"
)

Every tree has a root node, which is created by calling ExplorerTree$new. The tree stores the ids of all its nodes and therefore guarantees that all its ids are unique.

Add a new node to the tree

Right now we have a tree consisting of only one node, the root node. We want to add another node to the tree. To do that, we need to take the root node and add a child to it. We achieve that by calling get_root_node on our tree, which returns - as you would suspect - the root node. Every node has the method add_child, which creates a new node and adds it as a child to the calling node.

explorer_tree$get_root_node()$add_child(
  id = "first_child",
  explorer_class = "__group__",
  object = Object$new(),
  return = "self"
)

Let's look a little bit closer at the add_child method. We add a new node with id "first_child". This node is of explorer class "group".

Every node may have an explorer_class. Nodes, that share the same explorer_class behave similar inside of the explorer visualisation. The shinyExplorer package provides you with some basic explorer classes, but you are free to create your own explorer_classes using ExplorerClass$new as described in the vignette Create your own explorer class. Every node also has an object attached to it. This object can be of an arbitrary data type. One explorer_class is usually designed to work well with one data type and operate on it. The default object is an object of class Object, which only possesses name and id.

The last argument to the add_child method decides whether this method returns the calling node ("self", the default) or the new child node ("child").

# Compare the following two cases
# A: Add two children to the tree
explorer_tree$get_root_node()$add_child(
  id = "child1"
)$add_child(
  id = "child2" 
)

# B: Add child and grandchild to the tree
explorer_tree$get_root_node()$add_child(
  id = "child",
  return = "child"
)$add_child(
  id = "grandchild"
)

Visualize the tree

Now that you created your first tree, you may visualize it inside your Shiny app using the explorer module. In case that you've never used a module before - it is very simple yet powerful. Modules can be understood as apps inside of your app. They as well consist of a server function for the functionality and a UI function for the layout. For more details about modularizing your Shiny app see this article on the Shiny website.

# UI function:
ui <- function(id) {
  ns <- shiny::NS(id)
  shiny::tagList(
    # some UI
    explorer_ui(id = ns("id_explorer"))
    # some more UI
  )
}

# Inside your server function call:
shiny::callModule(
  module = explorer,
  id = "id_explorer",
  .root_node_r = shiny::reactive(explorer_tree$get_root_node()),
  .explorer_classes = explorer_classes
  # Further arguments to explorer
)

# Somewhere before calling the module, you must create the list of explorer_classes
# used in your app.
explorer_classes <- list(
  group_explorer_class()
  # Further explorer classes defined by yourself
)

Notice that we don't pass our tree to the explorer module, instead we take one node of the tree (in our example this is the tree's root node). The explorer module's visualisation will only show all nodes, that are descendents of the node you passed to it and none of its ancestors. Therefore you could create just one tree for your whole application and only visualize parts of it, where it is needed. For the same reason you are able to control, nodes of which explorer classes are visible to or addable by the user. Imagine a tree containing some nodes representing datasets, other nodes representing linear models. In your master view all nodes are visible, whereas in more specific views only linear model nodes are visible or only dataset nodes.

explorer takes an argument named .explorer_classes, which is a list of explorer_classes either created by yourself or taken from the explorer_classes that are included in shinyExplorer. You should define this list as a global variable and pass it to every explorer you use, regardless of if a particular explorer_class is used in this tree or not. Passing unused explorer_classes produces a minimal overhead when the module is initialised, whereas omitting an used explorer_class will result in an error.



DavidBarke/shinyExplorer documentation built on Aug. 28, 2020, 8:54 p.m.