SpaDES.shiny
package developmentvignettes/iii-package-devel.Rmd
iii-package-devel.Rmd
This document is intended for contributors to the development of the SpaDES.shiny
package. For users looking to get started building basic SpaDES.shiny
apps, see the introductory vignettes.
Please review the Contributor Guidelines.
The SpaDES.shiny
package consists of a set of shiny modules, an app generator and templates. The generator takes application metadata and uses templates to build a standalone application. Modules implement reusable parts of application that can be used to speed up the implementation process.
App generator builds new application in a chosen directory based on application metadata. In the directory there is a ui.R
and server.R
created together with all needed files. Generator uses templates (described in next section) to generate the code.
Entry point of generator is newApp
function. Application metadata is passed to other functions to build different parts of the app.
Generated applications use shinydashboard
, where each menu item is a shiny
module.
Application templates are located inst/templates
. Any static parts of application that are generated by the generator should be put here. Generator uses the whisker
package to generate files from templates. In order to add a new UI/server component, create a new file in inst/templates/
directory with the .template
extension.
Inside the template write code that you’d like to have generated. Put variables in “mustache” form ({{variable}}
). By default whisker applies html escaping on the generated text. To prevent this use {{{variable}}}
(triple) in stead of {{variable}}
(double).
Shiny modules in this package are generic components that can be used to bootstrap the application. The module should have a generic purpose and the main aim of developer should be to make this module reusable in different applications.
When building a new shiny module try to extract as much code as possible to separate modules that can be reused in other use cases. For example if you are building a shiny module that consists of a table, plot and a slider divide it into three modules each representing separate logic that can be reusable - a table view of a data.frame, a plot and a slider. First always check if there already exists a module that does the job.
Take a look at rastersOverTime
module. The aim of this module is to display a map with rasters that change over time. We want to be able to also change underlying polygons that are displayed and show histogram of raster values.
We can divide this module into smaller independent components. rastersOverTime
module actually consists of a:
This division gives us 7 independent generic components (actually 6 components - slider is used twice) that can be used in any combination.
In the end your code may look as follows:
rasterIndexValue <- callModule(slider, "rastersSlider")
polygonIndexValue <- callModule(slider, "polygonsSlider")
...
callModule(tilesUpdater, "tilesUpdater", mapProxy, urlTemplate, session$ns("tiles"),
addTilesParameters = addTilesParameters, addLayersControlParameters = NULL)
callModule(summaryPopups, "popups", mapProxy, click, raster, polygons)
callModule(polygonsUpdater, "polygonsUpdater", mapProxy, polygons, weight = 0.2)
callModule(histogramForRaster, "histogram", sampledRaster, histogramBreaks = breaks,
scale = rasterScale, addAxisParams = addAxisParams,
width = 1, space = 0)
What is more - if someone wants to create a map with raster selection and popups - they can just take a map, slider, raster updater and summary popup. A user can decide to implement different way of selecting the raster - they’ll just use another module instead of the slider.