class: center, middle, inverse, title-slide .title[ # Reactivity ] .subtitle[ ## SISBID 2024
https://github.com/dicook/SISBID
] .author[ ### Di Cook (
dicook@monash.edu
)
Heike Hofmann (
hhhofmann4@unl.edu
)
Susan Vanderplas (
susan.vanderplas@unl.edu
) ] .date[ ### 08/14-16/2024 ] --- # Elements of Reactivity .pull-left[ - Sources - Any input widget is a source<br/><br/> - Conductors - Use input and pass values to another component<br/><br/> - Observers - Any output is an observer ] .pull-right[ ![](reactivity.png) ] --- # Two Conductors - Reactive expressions and reactive events are two types of conductors<br/><br/> - Reactive expressions are the archetypical conductor: <br/><br/> - envelope functionality used in multiple places of an app - run evaluations only once - store current values - update when inputs change<br/><br/> - Reactive events are only triggered by specific events (e.g. click on an action button) --- # Reactive Expressions ``` r rval <- reactive({ ... }) ``` Called like a function as `rval()` - Reactive expressions are executed **lazily** and values are **cached**<br/><br/> - **Lazy**: Evaluated on demand as requested by a reactive endpoint<br/><br/> - **Cached**: (re-)evaluated only when the value of a dependency changed --- # Reactive Events ``` r rval <- eventReactive(actionbutton, { ... }) ``` Called like a function as `rval()` - reactive events are executed even more **lazily**<br/><br/> - only on demand<br/><br/> - requested by an actionButton (usually) --- # Example: Submission Form .pull-left[ - In RStudio open file `app.R` in `03_submission`<br/><br/> - Run the app (a couple of times) <br/><br/> - Turn on showcase mode: ``` r runApp("03_submission/", display.mode = "showcase") ``` ] .pull-right[ ![Submission form applet screenshot](submission_form.png) ] --- class: inverse middle # Your turn .pull-left[ - Open the file `03_submission.R` - The package `colourpicker` implements a color wheel as an input widget - Allow users to change the color of the dots in the dot plot - What other interactive elements can you think of adding? Answers are in `03b_submission.R` ] .pull-right[ ![Screenshot of completed app](your-turn-screenshot-days.png) ]
−
+
05
:
00
--- # Conditional Panels .left-column[ ![Screenshot of the inputs without a conditional panel](without-conditional-panel.png) ![Screenshot of the inputs with a conditional panel](with-conditional-panel.png) ] .right-column[ - Showing a color picker before it is needed could confuse app users <br/><br/> - `conditionalPanel(condition, ...)` allows us to encapsulate elements of the UI and only show them when `condition` is fulfilled<br/><br/> - Here, a condition of `condition = 'input.submit > 0'` is true when the submit button was pressed at least once.<br/><br/> - This is implemented in `03c_submission.R` ] --- .pull-left[ # App Layout - The body is laid out using a responsive grid - responsive: adapts to different screen sizes - different on a cell phone than a laptop - boxes are rearranged automatically - Structure is introduced by cards ``` r card1 <- card( card_header("Hi, I'm a card"), class = "bg-primary", "I contain some information - ", "text, plot, image, input area...", "your choice!") ``` ] .pull-right[ .move-up[.move-up[![The app layout has 12 columns (width) and you can specify rows as well.](bslib-layout-cards-cols.svg)]] ![Row heights can be specified as well](bslib-layout-cards-rows.svg) ] --- # Cards .pull-left[ .move-up.center.huge[`04_layout.R`] - Cards help with structuring output<br/><br/> - Cards have a `class` parameter - `bg-xxx` produces a colored box - `border-xxx` produces a box with a colored outline - `card_header(..., class = "bg-xxx")` produces a box with a colored header - `?validStatuses`, represented by `xxx` above, are `primary`, `secondary`, `success`, `info`, `warning`, `danger`, `light`, `dark` ] .pull-right[ .move-up[![Demonstration of an app with different box statuses](bslib-layout-cards-narrow.png)] ] --- # Nested Layouts .pull-left[ - Body is wrapped in a `page_fillable` function<br/><br/> - Cards are aligned using columns<br/><br/> - Additional rows can be created by nesting `layout_columns()` functions<br/><br/> ``` r body <- page_fillable( layout_columns( col_widths = c(2, 4, 4, 2), # 12 cols per row row_heights = "600px", card1, layout_columns(card2, card3, card5, col_widths = c(12, 12, 12), row_heights = "auto"), card4, card6) ) ``` ] .pull-right[ .move-up.center.huge[`04_layout2.R`] ![Nesting rows and columns](bslib-nested-col-layout.svg) ] --- # Nested Layouts .pull-left[ - Body is wrapped in a `page_fillable` function<br/><br/> - Cards are aligned using columns<br/><br/> - Additional rows can be created by nesting `layout_columns()` functions<br/><br/> ``` r body <- page_fillable( layout_columns( col_widths = c(2, 4, 4, 2), # 12 cols per row row_heights = "600px", card1, layout_columns(card2, card3, card5, col_widths = c(12, 12, 12), row_heights = "auto"), card4, card6) ) ``` ] .pull-right[ .move-up.center.huge[`04_layout2.R`] ![Nesting rows and columns](bslib-nested-col-layout-interior.svg) ] --- # Other Layouts - `page_fillable()` has different behavior from `page_fluid()` and `page_fixed()` - see [this article](https://rstudio.github.io/bslib/articles/filling.html) for more information about fillable containers. - `page_navbar()` can be used to create tabs across the top (more on this in a minute) - `sidebar()` allows for common inputs across all tabs - `layout_column_wrap()` can accomplish some [very neat tricks](https://rstudio.github.io/bslib/articles/column-layout.html) ``` r layout_column_wrap( width = NULL, height = 300, fill = FALSE, style = css(grid_template_columns = "2fr 1fr 2fr"), card1, card2, card3 ) ``` - [Shiny UI Editor](https://rstudio.github.io/shinyuieditor/) is currently in Alpha but allows UI creation without writing code --- # Tab Layouts Code: 05_tabsets.R .panelset.sideways[ .panel[.panel-name[tab1] ![](bslib-navset-pill-list1.png) ] .panel[.panel-name[tab2] ![](bslib-navset-pill-list2.png) ] .panel[.panel-name[tab3] ![](bslib-navset-pill-list3.png) ] ] --- # Tabs - Different options for multi-page applets: .panelset.sideways[ .panel[.panel-name[`navset_tab()`] ![](bslib-tabset.png) ] .panel[.panel-name[`navset_pill()`] ![](bslib-pill.png) ] .panel[.panel-name[`navset_bar()`] ![](bslib-bar.png) ] .panel[.panel-name[`navset_pill_list()`] ![](bslib-pill-list.png) ] .panel[.panel-name[`navset_card_tab()`] ![](bslib-card-tab.png) ].panel[.panel-name[`navset_card_pill()`] ![](bslib-card-pill.png) ] ] --- class: inverse middle # Your Turn Modify the code in 05_tabsets.R to use a `page_navbar()`. - What modifications do you have to make? - Can you add a sidebar using the `sidebar()` function?
−
+
05
:
00
--- # Resources - RStudio Tutorial: https://shiny.rstudio.com/articles/reactivity-overview.html<br/><br/> - Shiny Cheat Sheet: https://raw.githubusercontent.com/rstudio/cheatsheets/master/shiny.pdf<br/><br/> - Gallery of Shiny Apps: https://shiny.rstudio.com/gallery/ - bslib documentation: https://rstudio.github.io/bslib/