need to be called with input, output and session. it should not be used directly,
only using component function.
Methods
- Documentation
For full documentation of each method go to https://stash.intranet.roche.com/stash/projects/DIVOS/repos/battery/browse
BaseComponent$new(...)This method is used to create base battery object, it should never be created directly. Battery components should be created as inherited from this BaseComponent, but this should be done only using
componentfunctiongetByIdMethod return component with specific id
appendChildMethod add battery component as child this current component
removeChildMethod remove child component complementary to appendChild
nsMethod used to create namespaced identifier
createEventMethod will create battery event
emitPropagate events from child to parent
broadcastPropagate events from parent to all children
connectHelper method that will create binding between input event from shiny and battery event
disconnectMethod remove binding between input element and compnents events
onAdd event listener to given internal event or native input
offMethod removes event listener(s) added by
onclassMethod return name of this class - same as classname when crating the class
destroyMethod remove all observers created for this component
finalizeR6Class method that will be called when object is destroyed
addServiceMethod dynamically add service to battery component system
templateHelper method that create
shiny::htmlTemplatewith self and private as defaults variablespathMethod return path to the object in battery components tree
logMethod log messages that can be listen to with
loggerhelperloggerShortcut function to add listener to logger
renderFunction that should be overwritten in battery component
Public fields
id- string that
name- component instance name, set using
parent$appendChild(name)orcomponent$new(parent = self, component.name = name)services- environment that hold static services - objects shared across battery components tree. Services can be added using
component$addService(name, ANY)events- environment that will hold reactive values added by on or createEvent method
parent- parent component
children- list of components that are children of the component, this list will be used to when using
component$broadcast("name")input- shiny input object added in constructor of root class or inherited from parent
output- shiny output object added in constructor of root class or inherited from parent
session- shiny session object added in constructor of root class or inherited from parent
static- environment that can be used to save property into class, it will be shared with all instances of same battery component.
Methods
Method new()
R6Class method that will be called when object is destroyed
it just calls destroy
native R6 class constructor
this should never be overwriten by child components, they should only overwrite constructor that is not as problematic when not called super
Usage
BaseComponent$new(
input = NULL,
output = NULL,
session = NULL,
parent = NULL,
component.name = NULL,
services = NULL,
spy = FALSE,
...
)Arguments
input- shiny input object added in constructor of root class or inherited from parent
output- shiny output object added in constructor of root class or inherited from parent
session- shiny session object added in constructor of root class or inherited from parent
parent- parent battery component, if used you don't need to add
input,outputandsessioncomponent.name- name of the component to be used in component$parent$children
services- list of any static services that can be created on component initialization
spy- used in unit test to record component method calls (only user methods are recorded)
...- everything else is passed to
constructormethod that should be used in user components Method return component with specific idit will search the tree of components find name with specific id
Method createEvent()
Method will create battery event
this event can be triggered from R code it can also be broadcasted this function is called automatically when using on to create observer
Method trigger()
Method will trigger the event. It call every observer and invalidate every reactive context
Method emit()
Propagate events from child to parent
it will recursivly walk whole tree, and trigger only events that
have reactive values added with createEvent it will also trigger
all observers added with on
Arguments
name- name of the event to propagate
value- optional value to to set on reactive values (it will be access from component$events or inside observer
target- optioanl target that should be passed along the event can only be access from event handler added by
component$oninclude.self- shoult it also trigger on this component or only on children
.level- internal option for logger, that is used to created indent
Examples
\dontrun{
App <- battery::component(
classname = "App",
public = list(
constructor = function() {
self$on("update", function() {
print("I need to update")
})
panel <- Panel$new(parent = self, component.name = "panel")
self$outptu[[self$ns("panel")]] <- renderUI({
panel$render()
})
},
render = function() {
shiny::tags$div(
#...
uiOutput(self$ns("panel"))
)
}
)
)
Panel <- battery::component(
classname = "Panel",
public = list(
constructor = function() {
self$on(self$ns("button"), function() {
self$emit("update")
}, input = TRUE)
},
render = function() {
shiny::tags$div(
#...
actionButton(self$ns("button"), "Click Me")
)
}
)
)
## clicking on button will emit the event to the parent and print the message
}
Method broadcast()
Propagate events from parent to all children
methods similar to emit but it propagete event to children
if called on root component it will send message to all components
inside the tree.
Usage
BaseComponent$broadcast(
name,
value = NULL,
target = NULL,
include.self = FALSE,
.level = 0
)Arguments
name- string - name of the component to trigger
value- default value adde to component$events
target- string that indicate which battery component trigger the event it can be omited if so it will use same object that called the method
include.self- flag that indicate if event should also be called on self
.level- internal option for logger, that is used to created indent
Examples
\dontrun{
App <- battery::component(
classname = "App",
public = list(
count = 0,
constructor = function() {
self$label <- label
self$on(self$ns("button"), function() {
self$count <- self$count + 2
self$broadcast("update", paste0("Update_number_", count))
}, input = TRUE)
counter <- Counter$new(parent = self, component.name = "counter")
self$outptu[[self$ns("counter")]] <- renderUI({
panel$render()
})
},
inc = function(count) {
self$label <- paste0("label_", count)
},
render = function() {
shiny::tags$div(
actionButton(self$ns("button"), "Click Me"),
uiOutput(self$ns("counter"))
)
}
)
)
Counter <- battery::component(
classname = "Counter",
public = list(
counter = 0,
constructor = function() {
self$createEvent("update")
},
render = function() {
self$counter <- self$counter + 1
shiny::tags$div(
paste("Counter", self$counter),
self$events$update$value
)
}
)
)
## first it will render the child with "Counter 1" (the value of events reactive
## reactive variable will be NULL, default value of events)
## after clicking the button it will increase the count in App by 2
## send event to children and it will in turn trigger render child again
## so it will display "Counter 2" and "Update_number_2"
##
## child render will be called twice and event handler on button once
}
Method connect()
Helper method that will create binding between input event from shiny and battery event
Method disconnect()
Method remove binding between input element and compnents events
complementary to connect
Method on()
Add event listener to given internal event or native input
Usage
BaseComponent$on(
events,
handler,
input = FALSE,
enabled = TRUE,
single = TRUE,
debounceMillis = NULL,
once = FALSE,
ignoreNULL = TRUE,
init = FALSE
)Arguments
events- character or character vector of internal event or input id
handler- function that can have value and target parameters (optional)
input- boolean that's indicate if event should be added to input otherwise it's internal battery event
enabled- boolean that enable event to easy toggle event
single- if used it will create only one event, it will always destroy old one
debounceMillis- if not NULL it will use
shiny::debounceon the functiononce- argument works the same as in
shiny::observeEventignoreNULL- argument works the same as in
shiny::observeEventinit- indicate if event should be triggered on init
Examples
\dontrun{
self$on(self$ns("inputValue"), function(value) {
print(paste("Input value is ", value))
}, input = TRUE)
self$on(self$ns("save"), function() {
print("user click save")
}, input = TRUE)
self$on("event", function(value, target) {
## this event can be fired with trigger/emit/broadcast
})
}
Method off()
Method removes event listener(s) added by on
if handler is NULL it will remove all listeners for a given event name
Method class()
Method return name of this class - same as classname when crating the class
Method destroy()
Method dfestroy component
It removes all observers created for this component also clear it also use other clean ups.
Method addService()
Method dynamically add service to battery component system
only one service with giben name can be added to the tree
same object will be accessed in every component in the tree.
there is one default service logger that is EventEmitter
Method template()
Helper method that create shiny::htmlTemplate
with self and private as defaults variables to be used in html (inside {{ }})
Method log()
Method log message that can be listen to, best way to add listener is to use self$logger("name", fn) in root component constructor each event is triggered with list(id, type, path, message, args)
Arguments
levels- vector of characters to listen (default names in battery are "battery" and "info")
message- message to log
type- default battery - additional value to distinguish the message in battery type is name of the method - or "method" inside user method
...- any arguments are added into args property
Method render()
Function that should be overwritten in battery component
this is convention that this function should return HTML (shiny tags) this function can have reactive value self$events. render function should not have children render if possible becasue update of parent will rerender the children. The proper way is to use renderUI in constructor and renderUI in render function for the children.
Examples
## ------------------------------------------------
## Method `BaseComponent$ns`
## ------------------------------------------------
if (FALSE) { # \dontrun{
battery::component(
classname = "Plot",
public = list(
constructor = function() {
self$output[[ self$ns("plot") ]] <- renderPlot({
## ...
})
},
render = function() {
shiny::div(
class = "container",
plotOutput(self$ns("plot"))
)
}
)
)
} # }
## ------------------------------------------------
## Method `BaseComponent$emit`
## ------------------------------------------------
if (FALSE) { # \dontrun{
App <- battery::component(
classname = "App",
public = list(
constructor = function() {
self$on("update", function() {
print("I need to update")
})
panel <- Panel$new(parent = self, component.name = "panel")
self$outptu[[self$ns("panel")]] <- renderUI({
panel$render()
})
},
render = function() {
shiny::tags$div(
#...
uiOutput(self$ns("panel"))
)
}
)
)
Panel <- battery::component(
classname = "Panel",
public = list(
constructor = function() {
self$on(self$ns("button"), function() {
self$emit("update")
}, input = TRUE)
},
render = function() {
shiny::tags$div(
#...
actionButton(self$ns("button"), "Click Me")
)
}
)
)
## clicking on button will emit the event to the parent and print the message
} # }
## ------------------------------------------------
## Method `BaseComponent$broadcast`
## ------------------------------------------------
if (FALSE) { # \dontrun{
App <- battery::component(
classname = "App",
public = list(
count = 0,
constructor = function() {
self$label <- label
self$on(self$ns("button"), function() {
self$count <- self$count + 2
self$broadcast("update", paste0("Update_number_", count))
}, input = TRUE)
counter <- Counter$new(parent = self, component.name = "counter")
self$outptu[[self$ns("counter")]] <- renderUI({
panel$render()
})
},
inc = function(count) {
self$label <- paste0("label_", count)
},
render = function() {
shiny::tags$div(
actionButton(self$ns("button"), "Click Me"),
uiOutput(self$ns("counter"))
)
}
)
)
Counter <- battery::component(
classname = "Counter",
public = list(
counter = 0,
constructor = function() {
self$createEvent("update")
},
render = function() {
self$counter <- self$counter + 1
shiny::tags$div(
paste("Counter", self$counter),
self$events$update$value
)
}
)
)
## first it will render the child with "Counter 1" (the value of events reactive
## reactive variable will be NULL, default value of events)
## after clicking the button it will increase the count in App by 2
## send event to children and it will in turn trigger render child again
## so it will display "Counter 2" and "Update_number_2"
##
## child render will be called twice and event handler on button once
} # }
## ------------------------------------------------
## Method `BaseComponent$on`
## ------------------------------------------------
if (FALSE) { # \dontrun{
self$on(self$ns("inputValue"), function(value) {
print(paste("Input value is ", value))
}, input = TRUE)
self$on(self$ns("save"), function() {
print("user click save")
}, input = TRUE)
self$on("event", function(value, target) {
## this event can be fired with trigger/emit/broadcast
})
} # }