-
Notifications
You must be signed in to change notification settings - Fork 72
/
cm110.Rmd
295 lines (222 loc) · 8.61 KB
/
cm110.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# (10) DashR: Layouts and Styling Dashboards
```{r include=FALSE}
knitr::opts_chunk$set(echo=TRUE, warning=FALSE, message=FALSE)
```
```{r}
library(tidyverse)
```
**This lecture is 100% complete.**
## Today's Agenda (10 mins)
- Announcements:
- New thing: I wil post the repl.it for each class here
- [Today's code](https://repl.it/join/dsnqaqbz-firasm)
- Part 1: Recap of multi-level callbacks [10 mins]
- Part 2: Restructuring the dash app [15 mins]
- Moving plot functions to `dash_functions.R`
- Moving components to `dash_components.R`
- Using `source(path/to/file.R)` to load objects
- Part 3: Layouts in Dash [45 mins]
- Header
- Sidebar
- Multi-column layouts
- Link to layout templates (by Matthew)
- Part 4: Looking ahead [5 mins]
- Next Tuesday we will deploy our app on the web so it's publicly viewable
- Before next class, [create a few heroku account](https://signup.heroku.com)
## Part 1: Recap of multi-level callbacks [10 mins]
Recap:
- `clickData`
- `ggplotly(p) %>% layout(clickmode = 'event+select')`
- `...+ scale_color_manual(name = 'Continent', values = continent_colors) + ...`
- Callbacks:
```
app$callback(
#update figure of gap-graph
output=list(id = 'gap-graph', property='figure'),
#based on values of year, continent, y-axis components
params=list(input(id = 'y-axis', property='value'),
input(id = 'yaxis-type', property='value')),
#this translates your list of params into function arguments
function(yaxis_value, yaxis_scale) {
make_plot(yaxis_value, yaxis_scale)
})
####NEW: updates our second graph using linked interactivity
app$callback(output = list(id = 'gap-graph-country', property = 'figure'),
params = list(input(id='y-axis', property='value'),
# Here's where we check for graph interactions!
input(id='gap-graph', property='clickData')),
function(yaxis_value, clickData) {
# clickData contains $x, $y and $customdata
# you can't access these by gapminder column name!
country_name = clickData$points[[1]]$customdata
make_country_graph(country_name, yaxis_value)
})
```
## Part 2: Restructuring the dash app [15 mins]
Live demo:
- `suppressPackageStartupMessages(library(plotly))`
- `suppressPackageStartupMessages(library(tidyverse))`
- Delete `htmlIframe(...` that we added for empty spacing, we'll learn a better way today!
- Comment out callbacks (for faster reloading) and set `debug=TRUE`
- Move functions to a new file called `dash_functions.R` (optional)
- Move components to a new file called `dash_components.R` (optional)
- At the top of your main app, source the two files above:
```
source('dash_functions.R')
source('dash_components.R')
```
- Just like we created Dash components and stored them as variables, let's also create layout elements and store them as variables:
```
## Specify App layout
app$layout(
htmlDiv(
list(
heading_title,
heading_subtitle,
#selection components
htmlLabel('Select y-axis metric:'),
yaxisDropdown,
htmlLabel('Select y scale : '),
logbutton,
#graph
graph,
graph_country,
sources
)
)
)
```
to:
```
## Specify layout elements
div_header <- htmlDiv(
list(heading_title,
heading_subtitle
)
)
div_sidebar <- htmlDiv(
list(htmlLabel('Select y-axis metric:'),
htmlBr(),
yaxisDropdown,
htmlLabel('Select y scale : '),
htmlBr(),
logbutton,
sources
)
)
div_main <- htmlDiv(
list(graph,
graph_country
)
)
## Specify App layout
app$layout(
div_header,
htmlDiv(
list(
div_side_bar,
div_main
)
)
)
```
## Part 3: Layouts and styles in Dash [45 mins]
### Styles
- Add styles to your `div_header`
- (Get your colours from [htmlcolorcodes.com](https://htmlcolorcodes.com)
)
```
## Add this property after your list of components
style = list(
backgroundColor = '#337DFF', ## COLOUR OF YOUR CHOICE
textAlign = 'center',
color = 'white',
margin = 5,
marginTop = 0
)
```
Run your app, make sure everything still works - you should notice your header is now a different colour and centered on the page.
- Add styles to your sidebar:
```
style = list('background-color' = '#BBCFF1',
'padding' = 10)
```
Here is a handy title of useful CSS properties:
| CSS property | Dash style | What does it do ? |
|------------- | ---------- | ----------------- |
| color | color | Sets the text color for elements |
| margin-top | marginTop | |
| margin-bottom | marginBottom | |
| margin | margin | [Sets the amount of space outside a block element (in pixels) ](https://www.w3schools.com/cssref/pr_margin.asp) |
| text-align | textAlign | [Aligns text left, right, center or justify] (https://www.w3schools.com/cssref/pr_text_text-align.ASP) |
Outside of this, there are hundreds of properties you could control to set every pixel where you want it to be - we will not fuss with such minutiae here!
For your apps, you are welcome to be as creative as you like.
If you have questions about how to do specific things, post on the Discussions repo as an issue and I'll try and get to it.
### Diving deeper into htmlDivs
Whiteboard sketch of what's going on...
### Flexbox
Let's quickly do a whirlwhind tour of the flexbox options that we will most likely use.
The first thing to understand is that the flexbox "system" has properties for the "flex container" and the "flex items" within a flex container.
The images from CSS-Tricks below illustrate the differences nicely.
First, here's the container:
![](https://css-tricks.com/wp-content/uploads/2018/10/01-container.svg)
And the items within the container:
![](https://css-tricks.com/wp-content/uploads/2018/10/02-items.svg)
To use the flexbox layout system in Dash, the first thing you need to do is attach the `'flex' = 'display'` property on a parent `htmlDiv` container.
Here is how to do it:
Start with a layout:
```
## Specify App layout
app$layout(
htmlDiv(
list(
# Div1 : for say, a sidebar
# Div2 : for the main content
)
)
)
```
to:
```
## Specify App layout
app$layout(
htmlDiv(
list(
# Div1 : for say, a sidebar
# Div2 : for the main content
), style = list('display' = 'flex')
)
)
```
There are many additional properties we could specify using the style property in Dash.
In fact, it is also possible to set style properties for individual elements (divs) in a parent container.
To do this, simply attach the `style = list()` to the appropriate div.
For example, let's say we wanted to make sure the sidebar took up at least 30% of the width in our container.
We would need to add `'flex-basis' = '30%'` as a style property to the "item" inside a container.
```
style = list('flex-basis' = '30%'),
```
A [through guide to the flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) may be useful if you want to explore options.
Here are the (most important) flex properties summarized in a table for you:
| Flex property (Dash syntax) | Container or Item? | What does it do ? |
|------------- | ---------- | ----------------- |
| 'display' = 'flex' | Container | [Creates flexbox div](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) |
| 'flex-wrap' = 'wrap' | Container | [Controls whether elements wrap if window size is reduced](https://css-tricks.com/almanac/properties/f/flex-wrap/)|
| 'justify-content' = 'center' | Container | [Justifies items within a container](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content)|
| 'flex-basis' = '20%' | Item | Defines the default size of an element before the remaining space is distributed. |
### Other layout examples
Feel free to explore one of the layouts from [this repo](https://github.com/matthewconnell/dashr_sample_layouts) created by Matthew as a starting point for your project apps.
### Final app
For full participation marks today, in your repository you should have a functioning app with all the elements (including restructuring the app) we discussed today in class.
## Part 4: Looking ahead [5 mins]
Here are three examples of **deployed** dashboards look like in R once layouts have been applied to them.
These were done by former students:
- [Boston Crime Dashboard](https://group-dash-milestone-4.herokuapp.com)
- [Interactive Movie Dashboard](https://movies214-milestone4.herokuapp.com)
- [Job Analyzer](https://dsci532-milestone4-r-107.herokuapp.com)
### Before next class
- Next Tuesday we will deploy our app on the web so it's publicly viewable
- Before next class, please [create a few heroku account](https://signup.heroku.com)
```
Heroku ID: ## YOUR ID HERE
```