-
Notifications
You must be signed in to change notification settings - Fork 6
/
basic-ui.Rmd
executable file
·307 lines (234 loc) · 8.45 KB
/
basic-ui.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
296
297
298
299
300
301
302
303
304
305
306
307
# Basic UI
### Exercise 3.2.8.1 {-}
When space is at a premium, it's useful to label text boxes using a placeholder that appears _inside_ the text entry area. How do you call `textInput()` to
generate the UI below?
<br>
<center>
![placeholder](images/placeholder.png)
</center>
:::solution
#### Solution {-}
Looking at the output of `?textInput`, we see the argument `placeholder` which
takes:
> A character string giving the user a hint as to what can be entered into
> the control.
Therefore, we can use the `textInput` with arguments as shown below to generate
the desired UI.
```{r eval=FALSE}
textInput("text", "", placeholder = "Your name")
```
:::
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
### Exercise 3.2.8.2 {-}
Carefully read the documentation for `sliderInput()` to figure out how to
create a date slider, as shown below.
<br>
<center>
![placeholder](images/date-slider.png)
</center>
:::solution
#### Solution {-}
To create such slider, we need the following code.
```{r eval=FALSE}
sliderInput(
"dates",
"When should we deliver?",
min = as.Date("2019-08-09"),
max = as.Date("2019-08-16"),
value = as.Date("2019-08-10")
)
```
:::
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
### Exercise 3.2.8.3 {-}
If you have a moderately long list, it's useful to create sub-headings that
break the list up into pieces. Read the documentation for `selectInput()` to
figure out how. (Hint: the underlying HTML is called `<optgroup>`.)
:::solution
#### Solution {-}
We can make the `choices` argument a list of key-value pairs where the keys
represent the sub-headings and the values are lists containing the categorized
elements by keys. As an illustration, the following example separates animal breeds into two keys (categories): "dogs" and "cats".
```{r, eval=FALSE}
selectInput(
"breed",
"Select your favorite animal breed:",
choices =
list(`dogs` = list('German Shepherd', 'Bulldog', 'Labrador Retriever'),
`cats` = list('Persian cat', 'Bengal cat', 'Siamese Cat'))
)
```
If you run the snippet above in the console, you will see the HTML code needed
to generate the input. You can also see the `<optgroup>` as hinted in the
exercise.
:::
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
### Exercise 3.2.8.4 {-}
Create a slider input to select values between 0 and 100 where the interval
between each selectable value on the slider is 5. Then, add animation to the
input widget so when the user presses play the input widget scrolls through
automatically.
:::solution
#### Solution {-}
We can set the interval between each selectable value using the `step`
argument. In addition, by setting `animate = TRUE`, the slider will
automatically animate once the user presses play.
```{r, eval=FALSE}
sliderInput("number", "Select a number:",
min = 0, max = 100, value = 0,
step = 5, animate = TRUE)
```
:::
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
### Exercise 3.2.8.5 {-}
Using the following numeric input box the user can enter any value between 0
and 1000. What is the purpose of the step argument in this widget?
```{r, eval=FALSE}
numericInput("number", "Select a value", value = 150, min = 0, max = 1000, step = 50)
```
:::solution
#### Solution {-}
The step argument is the amount by which the `numericInput` value is
incremented (resp. decreased) when the user clicks the up (resp. down) arrow.
In the previous example, when the user clicks the up (resp. down) arrow the
numeric value will increase (resp. decrease) by 50. Note: by using a
`numericInput` the user still has the ability to type *any* number.
:::
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
### Exercise 3.3.5.1 {-}
Re-create the Shiny app from the plots section, this time setting height to
300px and width to 700px.
:::solution
#### Solution {-}
The function `plotOutput` can take on static `width` and `height` arguments.
Using the app from the plots section, we only need to add the height argument
and modify the width.
```{r eval=FALSE}
library(shiny)
ui <- fluidPage(
plotOutput("plot", width = "700px", height = "300px")
)
server <- function(input, output, session) {
output$plot <- renderPlot(plot(1:5), res = 96)
}
shinyApp(ui, server)
```
:::
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
<!---------------------------------------------------------------------------->
### Exercise 3.3.5.2 {-}
Update the options for renderDataTable() below so that the table is displayed, but nothing else (i.e. remove the search, ordering, and filtering commands). You’ll need to read ?renderDataTable and review the options at https://datatables.net/reference/option/.
```{r, eval=FALSE}
ui <- fluidPage(
dataTableOutput("table")
)
server <- function(input, output, session) {
output$table <- renderDataTable(mtcars, options = list(pageLength = 5))
}
```
:::solution
#### Solution {-}
We can achieve this by setting `ordering` and `searching` to `FALSE` within the
`options` list.
```{r eval=FALSE}
library(shiny)
ui <- fluidPage(
dataTableOutput("table")
)
server <- function(input, output, session) {
output$table <- renderDataTable(
mtcars, options = list(ordering = FALSE, searching = FALSE))
}
shinyApp(ui, server)
```
:::
### Exercise 3.4.6.1 {-}
Create an app that contains two plots, each of which takes up half the app (regardless of what size the whole app is)
:::solution
#### Solution {-}
When creating the layout of a shiny app, you can use the `fluidRow` function to
control the width of the objects it contains. This function can have columns
and such columns can be set to have widths ranging from 1-12. Note that columns
width within a `fluidRow` container should add up to 12.
For our exercise, we need two columns of 50% width each, i.e., we should set
the width of each column to 6.
```{r, eval=FALSE}
library(shiny)
ui <- fluidPage(
fluidRow(
column(width = 6, plotOutput("plot1")),
column(width = 6, plotOutput("plot2"))
)
)
server <- function(input, output, session) {
output$plot1 <- renderPlot(plot(1:5))
output$plot2 <- renderPlot(plot(1:5))
}
shinyApp(ui, server)
```
:::
### Exercise 3.4.6.2 {-}
Modify the Central Limit Theorem app so that the sidebar is on the right
instead of the left.
:::solution
#### Solution {-}
Looking at `?sidebarLayout` we can simply set the `position` argument to
`right`. We only need to modify the UI of the app.
```{r, eval=FALSE}
ui <- fluidPage(
headerPanel("Central limit theorem"),
sidebarLayout(
position = "right",
sidebarPanel(
numericInput("m", "Number of samples:", 2, min = 1, max = 100)
),
mainPanel(
plotOutput("hist")
)
)
)
```
:::
### Exercise 3.4.6.3 {-}
Browse the themes available in the shinythemes package, pick an attractive
theme, and apply it to the Central Limit Theorem app.
:::solution
#### Solution {-}
We can browse the themes [here](https://rstudio.github.io/shinythemes/) and
apply it by setting the `theme` argument within `fluidPage` to
`shinythemes::shinytheme("theme_name")`
```{r, eval=FALSE}
library(shinythemes)
ui <- fluidPage(
theme = shinythemes::shinytheme("darkly"),
headerPanel("Central limit theorem"),
sidebarLayout(
position = "right",
sidebarPanel(
numericInput("m", "Number of samples:", 2, min = 1, max = 100)
),
mainPanel(
plotOutput("hist")
)
)
)
server <- function(input, output, session) {
output$hist <- renderPlot({
means <- replicate(1e4, mean(runif(input$m)))
hist(means, breaks = 20)
})
}
shinyApp(ui, server)
```
:::