Reactive Web Dashboards with Shiny Transcripts
Chapter: Advanced UIs
Lecture: Render express
Login or
purchase this course
to watch this video and the rest of the course contents.
0:00
In the last session, we learned a little bit about how to build dynamic user interfaces with Shiny by updating input elements.
0:08
So we had a little button. When you click that button, it changed something about the user interface.
0:12
But what if we want to take that one step further and actually add or remove things?
0:17
So have your whole application actually dynamically respond to the user.
0:22
One of the great things about Shiny is that it has a really robust pattern for doing that called Render Express.
0:30
So in this application here, we're going to try to build a password-authenticated dataframe. This is just a basic one.
0:36
I wouldn't use this for anything, you know, any sort of actual serious security purposes, but it's a good illustration.
0:44
So we're going to add, first of all, an input text. Oops. And we'll call that ""password,"" and the label will be ""enter password.
1:01
What we want to do here is have the user enter a password and only show the dataframe when that password is correct.
1:09
So in this case, it's going to be ""penguins. One way we might want to do that is with a conditional.
1:15
So we would say ""input password equals penguins,"" and if it does, say ""render dataframe,"" and
1:32
define our little data function that returns the dataframe.
1:37
But this is going to fail with an error, because we're trying to call this input password outside of a reactive context.
1:43
So remember, whenever you try to call input outside of a render function or a reactive
1:49
calculation or reactive effect, you're going to get this error, ""no current reactive context,
1:52
because Shiny doesn't know what to do with that call outside of a render function.
1:56
Those render functions kind of define the nodes of our reactive graph, so if we don't
2:00
have those nodes, we can't really figure out when to render things, or what, in fact, to render.
2:06
The solution to this is to use the decorator renderExpress. Decorator renderExpress is kind of a pretty generic way of a renderer, which doesn't take
2:14
a particular output, it doesn't take a plot or a table. Instead it creates some Shiny express code, which are then added to your application under
2:23
certain contexts. So we'll create another function here, and I'm going to call this ""dynamic data,"" just to separate it from the inner renderer.
2:35
And now if I run this, I'm not going to get that reactive error, because this is taking place within a reactive context.
2:43
And in fact, if I go and I type ""penguins,"" I'm going to get the data frame out.
2:48
So this is a really great pattern, and it differs—it's very different from the pattern
2:53
we used before, updating an existing element, because the data is actually not in the application when the user starts it up.
3:01
So if I open this up, I can prove this to you by using something called the Chrome developer tools by inspecting the HTML.
3:08
I promise this is the only HTML we're going to look at in this course.
3:11
And you don't need to be able to really read this super well, but just notice that there's kind of only one thing with an input ID.
3:17
So the only thing that's here that's kind of Shiny-related is basically this input password ID.
3:24
So there's nothing down here in the bottom part where the data frame is going to go.
3:28
You can sort of see over here, if we close up that div, there's a bound output called dynamic data,"" but there's no data in here.
3:35
There's nothing about the penguins dataset. And every time I make a change here, this application is going to re-render, and each
3:42
time it's going to check, ""Did he enter the password correctly? Should I render that data?
3:46
And each time it's going to say, ""No, not going to render anything,"" until I get here.
3:51
And suddenly, you see there's actually some stuff in this bound output.
3:54
You see the data frame over here, and now when you look down here, there's a Shiny data frame, and it's got a bunch of different things in there.
4:03
Once the password has been entered correctly, it's rendering this output. And you can put any type of Shiny code in a render express.
4:12
So for example, I'm going to have a little else statement down here, and I'm going to say, ""Please enter a password.
4:30
So this is going to be some code here, and when I first start it up, before I enter the
4:35
password, and the password is incorrect, I'm going to get this, ""Please enter a password prompt.
4:39
But when I actually do enter the password correctly, I'll end up with this bigger data frame. You don't necessarily have to have just one thing.
4:51
For example, I could have an input here. Let's call it ""slider. So now when I enter this, oops, missing a value.
5:14
So I can include the slider and the data frame as well. I haven't connected these two, but you could connect them in the same way that you connected
5:20
them in the previous exercises. And this kind of illustrates one of the funny things about render express.
5:26
This is a bit of a magic function, which you don't need to know too much about the magic.
5:31
But one sort of key thing here is that whenever you have a render express function, we're
5:36
kind of basically stepping into this function and reading it for, and parsing it to get the Shiny code that we then include in the application.
5:45
And as a result, it's important that render express functions don't have return values.
5:49
So you just type in the Shiny code that you want, and that's going to be printed.
5:53
So any kind of valid Shiny code that's in a part of the function that you end up in is going to be sent to the Shiny application.
6:02
So for example, if I have here, instead of ""uih1,"" I would do ""return uih1,"" I'm going to get an error.
6:09
And the error I'm going to get is very informative. It's going to tell you right away, ""Hey, don't use a return value.
6:15
Instead, it'll just render every printable line within the function body. So you don't need that. In fact, you can't use that with render express.
6:25
If you've used Shiny core or Shiny for R, this is very different from the render UI, which is the pattern in those cases.
6:32
And this is just a way of fitting this pattern into the express framework. So you don't need to think too hard about it.
6:40
Just remember that whenever you're using render express, don't use a return value. Just type the code that you want to be rendered to your application.
6:48
Render express is a lot more flexible than the update pattern that we used before, because
6:52
you can add things, remove things, include multiple things in your dynamic user interface.
6:58
And the input doesn't need to be there right when the application starts.
7:02
So it might be that only when a user enters one path of your application are you going to return a particular value. And that's the way of doing it.
7:11
So it's a powerful tool, and it's one that lets you build really flexible applications to suit pretty much any kind of user need for your application.