 Okay, then I want to welcome you here, everyone, to the tutorial structure, your app introduction to Shiny modules at the USART 2021. Shortly to myself, I'm Jonas, currently doing a PhD, but also do some Shiny programming on the site and yeah, basically got introduced there to Shiny modules and I think it's a very valuable tool and I want to show you today how to get started with this. So basically, yeah, this is about how to write better Shiny code here. I don't know who knows it a few that you start writing an app and then your app.rfi gets longer and longer and gets more confusing and you have to repeat code. Or you want to use one functionality from your app and another app. So these are problems I have, I have and for this modules are a really nice way and I will show you how to solve these problems and it will be structured this way that first, I give a very, very short recap of reactive programming and then I give an introduction into modules, what they look like, how to pass values to the modules, how to return values, also how to do this with reactive values and in the last step how to dynamically generate modules. Yeah, I asked you to always ask questions in between if something is not clear. Either raise your hand if it's, I think we are not so many so you can also just directly, I'm very happy for questions because I want you to understand the material and in between we always have some short exercises and I will tell you how this will be when we come to the exercises. But first I want to know a little bit about your Shiny skills and I want you to rate this, you should be able now to annotate the screen and you can stamp it basically here on the line between beginner to expert and how you would say your Shiny skills are that I have a better idea of who you are in terms of Shiny. I have to see where you, do you find the annotation for it? Exactly, you also have kind of a stamp function where you can leave a star or something like this if you want to. Okay, so most of you are more in the beginner section. So here are a few comments in the chat also saying that most of you are more in the first half. Okay, perfectly fine. So always tell me if I have to click with something that if I explain, should I explain more? Yeah, okay, then I will very now start with a very brief recap of reactive programming. So the usual way to, let me check that I remove the annotations. Here we go. So for reactive programming, I mean the usual way to do it is you are more procedural. So you declare n is one and then you calculate the result by one plus n and then you say, okay, now n should be two and so on. So basically you tell what to do and when. For reactive programming, it's more that you define how to do something but not exactly the steps. Now you have to do this, this, this and this. And one, yeah, one part of this reactive programming is the reactive, which basically define a rule how something is calculated. And maybe, so here you would see the result is an irrect if you say, okay, it's one plus if you have here a shiny input and it always gets updated automatically if the input n changes. And maybe you can picture this a bit like homework assignments because students won't do anything by themselves only when the teacher says, okay, now do it on input page this and then it gets updated automatically but if nothing changes, they won't do anything. And basically the other part we have our observers or experiments which are functions to, yeah, monitor one or several reactive values and they always re-execute the code in them when something changed. And maybe you can think of this of a, yeah, student checking if a teacher is approaching who's on the lookout and this changes then basically the code is executed in the observer. So maybe our students back to the places. And if you make a comparison, basically between reactors and observed events, vectors are callable. So you can use the value returned by the reactors. As I said, that they return a value, observe events are not callable and they don't return a value. So they're basically more for their side effects, vectors are lazy. So they only change when an input in them changes and observe events are eager. So they always check does, has something changed or not. And there's a very good talk about this by Joe Chang and I would recommend watching this if you still want further introduction into this. Okay, there's one thing in the chat. Okay. Okay, this very, very brief introduction. And we have any questions until this point. If not, I would go on. So this is now a very general part how to reduce code complexity a bit in the context of SHINee. So I always recommend using the style guide that your code is consistent. For example, you could use a tidy verse style guide, use meaningful names. And I would say this is an especially important in the context of SHINee. So for example, if you have a variable called NS, it's very meaningless, but your students are already more descriptive and you know what it contains. But for SHINee, I would also say be even a bit more descriptive. So maybe you have a data object which has information about the new students. And then you maybe have an output with a table. So I like to prefixes with table new students that I know, okay, now this is actually the, yeah, the random table and this is the data for the table. Then also use meaning for comments. So rather why you did something and what for example in SHINee, if you use the DT package, you could, for example, specify which columns should be editable and you do this by column number. And then it would be nice for example in the comments to say actually the column names, which you mean by these numbers, because maybe you're underlying data object changes and then this editable function. This doesn't mean anything to you anymore. Then you should reuse code. So you can write functions also in SHINee, but it's mostly interesting if for the non-reactive parts in SHINee, then document your functions. And for this, let you help you buy the Russian package and lastly use SHINee modules to really encapsulate code on the UI and server side. I'm sorry, I forgot this one point is don't put too much functionality into one reactive or render call. For example, if you use a render, render DT, render table thing, it's, I like it to not put all my data wrangling functionality also in this render table call, but use a reactive beforehand where I do the data wrangling and then just call this reactive within the render table call. Okay, I'm sorry, I forgot this now with the modules. What are SHINee modules? So if you would picture this as your SHINee app, so you have some inputs here, some buttons, you have some outputs, and you have some logic in here and a connector in your complete app. And now you basically want to reuse components. For example, you need this input buttons also for other parts. So other circuit boards or then in the analogy that in other SHINee apps or the output in other SHINee apps, you can try to break it down. And basically an app always contains part both of the UI and a server part. And this is really the specialty of this modules. And you can always think of SHINee modules as a mini SHINee app with a few additional nuts and bolts to make these modules work. So basically a bit more schematic. It looks like this. If you have here your main app, you always have this UI part and the server part, right? And the module looks the same. It has a module UI part and the module server part, which are also written separately. And then you can use them in the app, right? So in the UI part of your app here in purple, you can now use or include the module, the UI part from the module. And then in the server part also include the server part of the module. This is basically the high level idea of a module. And now we come to the general structure, how it looks like. So basically this is now our really a scaffold of our SHINee app. And you see here in the UI part of the main app, we call the UI part of the SHINee module. And it's always nice to basically, yeah, here's basically always the name of the module. Here it's just module. And then you notify that this is the UI part. The naming is more or less arbitrary, but it's really nice to have this part saying it's the UI part. And then the important part is to have the ID of the module, ID one, which has to be unique. And then in the server part, you have the, yeah, server function of the module. And then you need to use the same ID, because it's only this ID, this ties, yeah, the UI and the server part of the module together. Okay. And now this looks like when you, how you can already reuse the code of modules. So you can just call the same UI and server function of your module the second time, now with a different ID. And this is really the nice thing with reusing codes or modules. And yeah, in the schematic, this looked like this, you just, yeah, have this a second time here. And IDs for defining the namespacing, which I will come in a second. Is this clear so far? Are there any questions? Is this clear? Okay. See this one. That's perfect. Okay, then let's go on to the module structure itself. And this is really what the scaffold of the module looks like. Okay, there's a question by Matt Jensen. If the module is called MO, it would be MO, MO underscore UI. Yes, so it's basically, you're free to name it what you want. But it's not advisable. So you always use, should use the same name of the module, for example, MO. And then you can use underscore UI and underscore server to distinguish the UI part in the server part. But you can also leave out the underscore, just write uppercase status UI and server. It's really up to you. But I would recommend to use a consistent structure that you always know what is the server part and what is the UI part of your module. Because basically they're just functions, just R functions, and they're just tied together by this ID. So the naming of them is arbitrary. I hope this makes it clear. Less clear. Okay, let's see. I would say I explained the names facing a bit more with the IDs itself. And then I actually will code the module for your life. And I think then it makes it hopefully a bit more clearer how to distinguish the name of the module itself and the IDs. So please hang on for a second. And then I try to explain it a bit in more detail. So here for the module structure, so you see that the UI part of the module, again, this is just how I call it module. And then I use this underscore UI to say, okay, this is the UI part. It's just an usual R function of the ID. Then with this, you define the namespace. This is something I will come to you in a second. Just hang on. And then here you have a tag list. And I'm not sure if you've seen it before. Tag list is used in Chinese to basically structure together different input or output elements, Chinese output elements. And you can think of this a bit of more fancy list. So this makes sure that basically, if you define here in the R code, inputs and outputs, I mean, in the end, they have to translate it into HTML code to make it work. And the way this is defined in Chinese can lead to problems if you just would use a list and put them there. So they have the special tag list, which in the end, just make sure that you get the correct HTML code out of this. So you can basically think of this as a list where you put your UI elements here. And then in the module server part, this is again also just a function of UI. And then now you need a bit, yeah, this more machinery to make it work. So now you have to call a function called module server, which, yeah, sets up that everything works correctly in the module, which is a function again of the ID. And then this I think is, sorry, this is known from the usual main Chinese app that you have an input output session, how you just would define the server part of a normal Chinese app. And yeah, he basically sees a setup for the namespacing. And I will explain this now bit more details. So basically in Chinese, all IDs, so the IDs of the inputs and outputs, which are then put in the, which your reference in the R code, but then, I mean, in the end, also translated into HTML that everything works correctly need to be unique. And now if you reuse the module, you would have the same IDs, right? Because in the, if you write an ID in a module and use it twice, this would lead that, that you have the same ID twice, but this wouldn't work in the code. So you have to somehow have a mechanism to make also these IDs in the end unique. And for this, you use namespacing. And you maybe know namespacing in R from using packages. So there can be functions, right, in different packages, but with the same name. For example, there's a function called filter from the base or base R stats package, and from deep player, right? And if you want to be explicit in the R code, which function to use, you have to use the package name and then to double points that to specify which, which function you mean, and basically the same happens in, in this module code. So you generate namespace. So you use basically this uppercase and S of ID. And this is then a function that is same as science namespace, which depends on the module ID for every module instance. And basically what happens here, for example, your ID of the module is my underscore ID, generate namespacing function. And then you can use this, for example, if, if you make an select input with the ID selected call, then you have to prefix it with this namespacing function. And then you get out basically the ID name, which is prefixed by the ID of this module instance. This is something basically machinery, which, which other module itself, and you don't have to reference always these name, the same pressing before. But you have to keep it in mind when you set up your module. And here you see it in action. So if you define a UI function of a module, you first generate this namespacing function. And then if you make your I element, you need an input ID. And this has to be prefixed with this namespacing function. And then you set up. And the nice part with Shiny modules is that in the server part, you don't have any additional work. So you can just in the server part of the module reference to this input ID as start calculation and not an S start calculation. Okay. I would say that I demonstrate this now by coding this small Shiny module based app live. And afterwards we can discuss the open questions you also had with how to name modules and the difference to the ID. Okay. Just let me make it a little bit bigger for you. And now, so sorry, there's something in the chat. Yeah, Yannetic asks if it's actually as input, dollar start calculation. Exactly. This is the way how you would reference this in the module server. Okay. And now I want to show you a short module based app. How you do this, which just plots uses the empty cast data set and plots a graph. And you can basically select in every module instance, which column you want to have it applauded. So first, we need Shiny and plot two. And now I start, sorry, let's chat. For this, you just please watch and always please ask questions. And for me, it would be easy. Actually, if you unmute yourself to ask the question, because then it's a bit easier for me that I don't have to want to hear the chat by myself. And I can answer your questions how to do this. So this is really just for the long, and then in a second, you also have an exercise to do it by yourself. So now I start actually out with this module function. So I want in this module a selection which column to use, and then the plot output. And so first, I have to think about this module name. Here I call the module plot. So it's my plot module. And then this is the name, right? And then I use underscore UI to define the say that it's a UI function, but plot UI, plot UI, this would work as well. This is really up to you how you would want to name this. And this is just a usual function, which needs an ID, right? For the namespacing. And then first, I have to set up the namespacing function. And then I can start with a tag list. And I said I want to select input. So input ID. And now it's really important that I use here the namespacing. But then the input ID I can use what I want here. Selected call. And then, yeah, just set up the select input choices. And here I just use the call and empty cars. So this is my first input. And then within the tag list, I use the second UI element, then a plot output. This has an output ID. And again, I need to use the namespacing and then can choose an ID just and this is already done with the UI function. And now I need to write the server part of the module. So here again, I call this underscore server, but I could also just call it plot, but I wouldn't regret this. I could call it something like this. It's really up to you. And again, this is function of ID. And now I have to set up this module server function, which first takes ID as an input argument, and then the function with input output session. And now I can here code the logic I want. And here I don't have to take care of the namespacing. Okay. And here to make a chart. So you see I can just refer to plot and don't need the namespacing. Okay. And now plot. And here I do what I set before. If you have more extensive data, don't do it in the random plot stuff. I just do it here for brevity. Basically, do a GZ plot. We use empty cars. And then say, basically, you can choose the x column. This is the wrong. I don't know if you've seen this before. This is basically the new way to do it in GZ plot, but also dplyr to access. Basically, not if you want to have access to the column names, and you don't have it as a symbol, but as a string, you can use the stop beta argument because all the inputs from shiny with the column names are characters or strings. And then just say that we use mpg as our outcome, and then use point plot. And this basically already the functionality we need in our module server. Okay. And this is now that we set up the module. And now I called the main app part page. And now I don't need any extra UI. I just call the ID we just generated with our module. And for this, I call our plot UI function from the module. And I have to give the ID. And now this has nothing to do with how the module itself named, right? The module is plot either underscore UI underscore server. Now we have to give every module instance an ID. For example, this is the first instance of this plot UI. I'm calling so I could, for example, say this is module one. And this is already done what I need to do in the server part in the UI part. And now I can define the server part. And here, this, I also just need to call the module function and use the same ID for the instance as I used here for the UI. Right. So it's module one. And with this, I'm also done in the server. And I can call the app. And this is now our main app. And basically the UI is rendered from our module. And here I can use the different columns. Okay. Also, you find the code for this in the example section of the GitHub repo. So if you don't have to follow along all this, you can just look the code up. Okay. Let me check. Is there something in the chat? No, I hope this made it a little bit clear about how you call the, how to name the UI in server part of your modules and then use IDs for instances of the modules. Are there any questions left for this? Are you on us? Could you just help me or us understand what the tag list does and why it's necessary? Yes. And basically the tag list makes sure that the R code, which defines your eyes, is stored in such way that later on it can be correctly translated into HTML code. Because like my experience are how they basically, if you don't use a tag list, can lead to problems because I think there's, I'm not sure how the Internet is correctly worked. Some parts are to go from the R code to the HTML code and there can be hiccups if basically these UI elements are not separated in the correct way and basically tag list makes sure that they are separated in the correct way and then the correct HTML code can be generated when you start the app. Okay. Thanks. That was helpful. Thank you. Yes. The question, can you ask other arguments to modules than ID? Yes. And this is exactly what we will cover now in the next section. Okay. And basically here you already see this. Now if you have a function not only of UI, but we can use a different input. For example, here a button label to customize the label of our action button, for example. This is no problem. And this also works for the server function. And you just have to do this in the, basically the high-level function and don't have to change the server itself. And then just can use it here in your logic code, how you would use it in the main app. How to do this with reactive objects? I will show you a bit later now just with basically normal objects. Now a short word when to use modules. Modules are very good when you use both UI and the server part. If you only have your I part you want to repeat the only server part, then you can also use just normal functions. Modules are also good because you can basically test their activity within a module with test server. And yeah, as I said, if you want to have function that's only on the UI on the server side, you can just use normal functions. Okay. And now I want to come to your first exercise that you write your first module. And for this, I have prepared a short shiny app. I will show you. As you can see here, it's again empty cars. You can show the summary and for the summary choose different columns on which to base the summary on, right? And this is in the code just in a normal shiny app. And now I want you to encapsulate this functionality within a module. So basically that in your module, you have all this. You have a button show summary. You have a select input where you can choose the column name and then data table where you either see the complete data set or the summary. And speak then when you have this module, you have to make this module so that you can input different data sets so that you can use your model with the empty cars data set, but you can also use it with what did I say here? With the diamonds data set and the CO2 data set so that you call your module several times. So you have to keep in mind that you need input arguments in your module that can take the data set input because what you do in the module depends on your data set you put into there, right? Because the selected columns need to be depend on the data set. And for this, I will have breakout rooms for you. Let me check how many people we are now. 18 minus me, I would say then that we have four breakout rooms. And I think the easiest one is if one person in the breakout group can share their screen and that you all code together and try to find a solution. And I, of course, will hop between the breakout rooms, help you, you can ask for help. I think there's a button. If you have a question that I come to you, yeah, and see that you code your first shiny app and you find the overview also in the GitHub repo under exercises. Okay, let me see, breakout rooms. And I would say first, I give you 10 minutes and if you see if it's not enough, you can have a bit longer. And in the end, we will also discuss the solution here with all so that you know how to do it. And then I open the rooms, if there are not any questions before. Hey, welcome back to the main room. Let's see if everyone's back. No, we are eight so far. Okay, perfect. Yeah, I kind of bit through the breakout rooms and it seems that most of you can, yeah, we're pretty, pretty good at the solutions. So I just want to shortly go through my solution with you to make, have everyone on the same page and then continue. And if there are any questions in between, feel free to ask. Okay. So basically here with the modules, I first start to define the module UI again. And besides ID, now I also have this data set argument, right, because I want to be able to input different data sets. Then I need the namespace generation. Then I have the take list. And for the take list, I just basically copy and paste what I've before had in the main app. And now here, again, with the namespacing. And then basically the only other thing you had to change is that for the choices, you basically use the data set argument and not hard code the empty cars anymore. And then also for the server part, what you had to change was that you don't use hard code empty cars here, but that you use again a data set argument with, which you would output, right? This is what you had to change. And then in the UI part of the main app, you can just call the UI part of the module several times with different, with different data sets, and then also different IDs. So here I would have the ID empty cars when I call empty cars and so on. And then the same also in the server function that I use the same ID, when I use the same data set, right? And then I can execute this and now have this one after another with my modules. And so this is really nice reuse of the code we had to write both for the server part and for the UI part. And now you can just call your module. Okay, this was basically what I wanted to say about the solution under any questions left. If not, I go on to another very important part, which I call a bit module communications. So now we want to look at how to pass reactive as inputs to modules and return reactors as the output of modules. So, sorry, there's one thing in the chat. Okay, perfect. So how to pass reactive inputs into modules. If you look at this code, do you have an idea of what could be wrong with this code? Right, I again have here, so I just have the server part of the module and again have an input result, but now this should be result, which I then use here in the render text and I pass basically in reactive valve from the main server function to my module server. And do you have an idea what could be problematic with this code or not work as intended? It's about the context. Some of the viable code in the test test reactive function can't be found in the module server. And this is actually not the problem. So this would be found, but the problem here is basically, if you look test as a reactive, right? And module server is not how do you call it? You can pass reactive values to non reactive function. Exactly. This is a bit of a problem. And basically, if you would execute this code, it works, but it works because if you have a look here, here I evaluate me reactive, right? Test is reactive. And when I first basically when this code here is executed, so this module server set up, it evaluates test, directive value test, it just would return one, right? Because this is how test is set up. And then I call my module with result with a value one. So no matter how often then in the main server function, I change this reactive value test in the module, it always stays one. Because when you set up the module, it was set up with the value one. So it's not reactive. And this is really the main problem when you start out with passing reactive values to modules. You always have to pass un-evaluated values, un-evaluated reactive to modules. And what I mean with this is what we'll see in a minute. And this is really, if you just take one thing from this workshop, it's the sentence. Always input un-evaluated reactive values into modules. This is really key. So let's have a look here. Again, I have this test reactive file set up with one. With this, by using the brackets here, I evaluate it to the value one and call my module with a value one. No reactivity. But if I just pass the un-evaluated reactive without the brackets, then this works. And you will see in a second how to make it work within the module server. Because the reactors itself are basically just functions. And they are just functions. And if you use the brackets here, you evaluate the function. And the function will return the value at the current moment. And there's some shiny magic in the background, which set up these functions in a way that they are reactive and always return a different value when their value was changed through to reactivity. So this is why it works if you just pass the un-evaluated function to the module and then only within the module evaluate the reactive. Then you also have this reactivity within the modules. This is really key. And here, I show you this for reactive value. If you're reactive values, then it's a bit different. For example, if you have reactive values, it's a bit more like a list. And you can have different data objects within your list, different entries. For example, here, I have the test entry. And if you directly pass a test entry through your module server, it won't work because it's already evaluated the value. But if you just pass a complete reactive values element through the module server, it works. If you have inputs that are defined through your main app UI, right? So this is now in the main app, these inputs. And if you just use the input dollar test, this won't work because at this point, it gets evaluated, you just get the value back and not a reactive. Because this input is only reactive within the main server function or later on in the module server functions. So for this, it looks a bit more complicated. For this, you have to basically wrap your input from the UI within a reactive and then call it, call your module. Then this works. And this is really, this is key to understand how reactivity works modules. And you can see here how this thing gets evaluated. So I have my reactive value, right? I pass it un-evaluated into my module. And then within my module, now result is the reactive. Basically, right here, I give it to this argument result, because I pass an un-evaluated reactive value to result. Result is now my reactive in the module server. And I can evaluate it with the brackets. And then I also have reactivity within my module server. And here, I show this for the reactive value object. Here, this is what it looks like for reactive values object. I just input the reactive values object completely. And then, basically, I assign it to my result variable called result. And then I can here access one entry in this result, reactive object called test. And then it's reactive also here. And if I have my input here and it's wrapped in reactive, again, pass to this argument called result, then within the module server, use the brackets, evaluate it, and you have your reactivity. This is really key for this using reactive inputs. So this was a bit like, yeah, the quick version. Aren't there any questions to this? I know it was, yeah, a bit loud. I have a question. Yes. So in the bottom part, you see a result equals reactive. You wrap the input test inside the reactive, right? Can you wrap it in the module server function straight away? For example, result equals reactive bracket inside the module so you don't have to call it as a reactive in the server function? No, this won't work because this code is only executed once, right? Because this is only executed when you set up, when you here in the server function, this is only set up once in the beginning to set up the module server, right? And only then it is executed. And at the point of the execution, basically, you would only pass input dollar test to the result. And at the execution, this is evaluated to just one value and not to reactive. So you would always pass just one value to the result and therefore it is not reactive in the module server anymore. This is really key to do this on the main app side. There's nothing then you could do in the module part. Okay, thanks. Jonas, I have a very basic question. Yes. And that is regarding this curly brackets. When are they actually used and what are they standing for? Yes, basically, you pass basically the reactive takes code as an input. And here it would work without the curly brackets. The curly brackets basically just enclose the complete code you pass within in reactive, right? Because the reactive then evaluate this code and updates if the code within the reactive is updated. And the curly brackets are, for example, especially helpful if you have multiple lines. So if you just put an input dollar test here, you wouldn't need them. But like for me, I decided that I always use this curly brackets because then I won't forget them if I needed them. And for me, it's also a bit, to be honest, like when I look at Chinese code and see the curly brackets for me, it's always like, okay, there should be something reactive going on. This is why I stick to this pattern of writing it. Yes, makes a lot of sense. Because I've seen them sometimes and sometimes not. Yes. Yes, that's why I get a little confused. Yeah, no, I get it. And because you don't always need them, I would say it's always better to just use them. Then this is not in the source of bugs. Okay. If there are not any more questions, I have again an exercise for you. And this time with reactive inputs. So basically now, let me check here. What you should do now is that you rewrite the code from exercise one and yeah, just feel free to use my solution for this. And that for now, you have this checkbox input right for every module and say if it should be in, should be sure the complete data set or the summary. And now I want you to remove this from the module and just have one checkbox input for the complete app. And then if you check this checkbox input in the complete app, all instances of the module should change to the summary or back to the, yeah, just showing the complete data. I hope this is clear the exercise, if not, yeah, please, please ask if something is not clear what you should do now. And for this, I again sent you to the breakout rooms and would say roughly 10 minutes and I hop around and see if it works or if you need some help. Okay. Yeah, I was quite good what I've seen on the breakout rooms, very good. So I will quickly go through the solution. And again, if you have any questions, feel free to ask. And I think best is just unmute yourself. So basically, here in the UI part of the module, I removed the checkbox input, checkbox input, we don't need it anymore. Now it's in the main app, I will come to this in a second. You see here now in the main app, I have the checkbox input. And this is basically all I had to do on the UI part and a bit more trickier part was on the server side part. So now on the module part, module server part, I pass my input, which is now here the input now from the main app as a reactive. And I chose to call it the summary argument, but you can call it what you want. And then in the table server party of the there's additional input argument, the summary. And, you know, before here, we had the input slash, I think, summary, which came from the module UI part, which I now removed. Now I remove this additional argument. And here's important that you don't forget the brackets, right, to evaluate the reactive here, because here now you want always an actual value and not an un-evaluated reactive. And the rest actually works as before. And then if you execute it, now you see I only have once here this show summary, and I've clicked it, then all modules at once behave according to this reactivity. Okay, this was very short. The solution. Are there any questions to this? I'm really happy to take any questions. If not, I would go out in the interest of time go on. I think we also don't have time to do all the exercises, but I think the next one is okay. Because so far we've only used input values, right? But you can also return reactive values from modules. And here's the same as for the input. If you're here, you really need un-evaluated reactives to return to the main app, because otherwise you wouldn't have the reactivity then in the main app. And how you do it is that you put a return statement at the end of your function of this input output session function in your module server and have the return and then return the un-evaluated reactive. So here I feel reactive file, so I just return and just the function name and basically not with the brackets. And then on the server side of the main function, you can just assign basically the output of your server call to a variable, which you then can use in your main app. And now this is again, here also an un-evaluated reactive. So you can use this un-evaluated reactive in a reactive context in the server part. They are evaluated with the brackets. And then you're good to go. If you want to return several reactives from a module, you can do it with a list. And then basically have named arguments, named entries in your list. And here I return input or basically reactives from inputs and UI elements from your module UI. And they have to do the same to wrap it again in a reactive. Otherwise it won't be reactive in the main app. And you can see it here. I again assign the output from my module to a variable. And then here basically, because it's a list, I can call the elements of the list and evaluate it. Okay, see, there's one question. How about returning reactive values? I guess if you have not reactive values, but you have active values, then you would return the complete reactive values object without explicitly naming one specific entry in the list. Yeah, this works. Okay, so we have roughly 25 minutes left. So I have to see, I would say that just in the interest of time, just try out exercise 3a or if you are 3a to get one feeling for this. And then unfortunately, we have to go on that I can at least cover shortly the other part, which I think are important when starting with modules. So yeah, basically just use exercise 3a. And basically what you now should do is that you take the code from exercise 2. Again, you can use the solution from the solution folders and return the mod from the module return this selected column name reactivity reactivity and then show this in the main app in a text output. And for this, you just have to call your module once with empty cars. Yeah, so I would ask you now to try this out again in the breakout rooms. Are there any questions for this? Otherwise, I sent you again to the breakout rooms. How to store the outputs of dynamically generated modules. Also not super perfect. So yeah, something to look when you're more familiar with these concepts. Then I want to say something about nesting of modules. I had this question already before. It's perfectly fine that you can nest modules and you can of course do this because you can do code reuse and I like to do something for example to set up one module for like one page you have in your app or if you have like really big, I was like tap different tabs and I have one module for one tap. And then I can use other different modules within this tab module. And this is one way I like to structure, for example, apps. And basically calling a module within the module is not different than you would call it from the main UI, the only thing you have to keep in mind. So this is now here the module UI in which you call another module. So the outer module. And we've learned that within module UIs we have the namespacing functions, right? And so you have to just keep this in mind if you call in our module UI that you also namespace this. This is really the only thing you have to keep in mind. But this is the same pattern as you would do with any other IDs in the module UI function as well. And there's also an example app in the example folders in the repo that you can have a look and see how you can use nesting of modules in practice. Then, where does the module live? So for small stuff, you can just put it on top of your up.r, fire perfectly fine. You can have it in an extra folder and then source the scripts before calling the main app. Or if you actually have an R folder within your project, this is now sourced automatically. So RStudio actually recommends to put your scripts in this R folder and then the sourcing is done automatically. And if you have really big, tiny apps, you can also put them in a different package. And then at the beginning, like you would call library shiny, call your package, and then can access your additional modules. Then also one thing to keep in mind, because sometimes you see this code set out in the wild, there was an API change with shiny 1.5, which was not just one year ago. So you maybe find all our code module code, which looks a bit different, right? This is a current way to write code where you can basically this only is about the server part. So right now, the server part of the module needs this module server here, right? But then you can just call your server function in the main server, in the main app. Before, it looked a bit different. Basically, when you set up your server, you just had this function of input output sessions. It's super easy. But you had to actually use a different function called call module in the main app server function. And you sometimes see this still out there. So don't be confused when you see it. It's just an older way to write modules. But you don't have to actively write code in this way. Okay, let's skip this. What should be a module? Something you should you repeat often and where you need a UI in the server part, where you want to test your activity maybe separately. Then, as I said before, large self-contained parts of an app, for example, a complete app of an app. But you don't have to wrap single UI elements within a module. This is, yeah, I mean, there you have more work than actually benefit from it. Then you can directly use a UI element. Okay. And basically, the summary, I would say, don't forget the name spacing in the UI for all the IDs. Really, keep it in mind, always input and output un-evaluated reactive if something should be reactive from the app to the module or from the module to the server. Otherwise, it won't work. And then, yeah, I'm very sorry that we didn't have too much time to go this. If you want to dynamically add modules, use insert and remove your eyes. And I think with this, it's also time was completely done now. I'm not sure if you have time to answer questions here, but always feel free to reach out and write in the Slack channel if you have any more questions, I'm happy to answer. And I was very happy that you participated here. And I had a good workshop with you. Yeah, so thank you. I just, so hi. I just want to say quickly, if you want to stay for another 10 minutes, actually it's fine because for this tutorial, we don't have another one starting right afterwards. So if you need 10 minutes for questions, it's all right. I just... Okay, okay. Yeah, sorry. Now the last one was very quick. So I'm super happy if you have any questions and try to go a bit more into detail. Yes, I have a question. Thank you. Thank you very much for the tutorial. And do you know if there is a bank or a database or a website with a lot of modules, examples on the web? Hey, I don't really know to be honest. I mean, there's a packet called, I think, shiny widgets and I'm not sure if they actually have some used a bit of modules there. But I haven't come across really like a database based on modules or something like the Shiny Gallery with a lot of examples to reuse. Because I think there are a lot of interactions, interactivities with the input so that looks like and perhaps someone has the idea to do this. Yeah, maybe there's maybe there are epic samples of modules within this Shiny Gallery to be honest, I haven't looked so I really don't know. Yeah, probably the best starting point. Yeah, if there are not any more questions also, I'm super happy if you also just can do it via Slack or so give some feedback because it was the first time I heard this workshop. And yeah, I'm happy to see if you think we would want to know more details or bit different stuff. So I can adapt it for the future. Jonas, maybe you can elaborate a little on where you use the modules and when. So yeah. Yeah, for example, right now I'm working on an app which really has, I forget where it's like tabs or tabsets, but basically you can have yeah, really like different pages, different pages that you click on in the Shiny app and basically run as a different page and I'd like to have one module for every kind of page for this because then it's really easy that I don't get I don't know like 3000 lines of code scripts or something like this. But it's a bit more structured that I know, okay, this is responsible for this, this is responsible for this, this is responsible for this. And so this is one thing where I use like really this bigger modules. Then, for example, if you use a module with some functionality, for example, with a feedback button within an app, which is written as a module, so you can just call this module in every app you use. And then basically like how the feedback is passed on to the app developers is abstracted in this, in this module and you don't have to write it every time you for every app you develop. So this is something where I use modules. Yeah, so so far I've used more for high level stuff. But I would say especially with this, sorry, I was a bit quick, if you have these, sometimes you want to, I don't know, dynamically show plots and want to allow people to say, okay, in the data set, I want to have, I don't know, some elaborated plots or set of plots for this column or so. So you can also try to basically then group the functionality for generating these plots and I don't know, select a different size within a module and then dynamically call and also maybe remove these plotting modules. I think it always really depends a bit on the context, but I would also always try to think, do I have in the app some part of code which has an UI output and a server function with it, which I need several times. And I mean, in the beginning, it may be also a bit difficult because maybe it's always basically you need the same functionality, but always a bit different. So you maybe can also think about, can I abstract it a little bit so that I don't know, use my input arguments to the modules to make it always a little bit different. I don't know if you're, let's see if I have a concrete example for this. Yeah, again maybe for this plotting module, it's more again a toy example, right? But for example, you sometimes need a point plot, sometimes you need a line plot, something like this, but then the user should, I don't know, adjust all the colors or the line size by themselves. So you could make a plotting module where you have then as an argument the plot type issue, I don't know, defined when you call the module, but then you have this functionality too, that the user can adjust their, just the style of the plot by themselves within the module, which is the same for, I don't know, for all plot types, right? So that you can think of like, what can I extract away that I put this into a module and then, yeah, don't have to write all the code again, just slightly different just because I need another plot type or something like this. And then, yeah, I would say also stuff you use in several modules, I don't know if you, I don't know, have a, also, I don't know, user validation stuff or something like this. So what you want to use across modules, I think this is also super handy to have in modules. Great. Thanks a lot. Okay, I need more questions. So just in the chat there was also the recommendation to look at this fantastic golden package, which I think is a really good tip also, which has a bit more, yeah, I would say it's a bit more opinionated package and how to structure your app, but which can really provide you a good scaffold to start and also, yeah, works natively with modules. Yeah, and as I said, also feel free to reach out after the tutorial. Okay, if there are not any more questions, I would say that we can close the tutorial and again, thank you for all the attendees.