shiny.router - a simple routing package for Shiny Dashboards

By:
Appsilon Team
December 6, 2016

<blockquote>Update 22nd of October, 2018. We have updated shiny.router package and realeased it on <a href="https://cran.r-project.org/web/packages/shiny.router/index.html" target="_blank" rel="noopener noreferrer">R Cran</a> and <a href="https://github.com/Appsilon/shiny.router" target="_blank" rel="noopener noreferrer">GitHub</a>. <a href="https://appsilon.com/shiny-router-package/" target="_blank" rel="noopener noreferrer">Full post on shiny.router update with plenty of examples.</a></blockquote> <strong>The time has come</strong> to release the first of our internal tools we use on a regular basis when developing <a href="https://shiny.rstudio.com/" target="_blank" rel="noopener noreferrer">Shiny</a> apps for our customers. In just a few lines of code added to your project, you get a helpful routing mechanism that allows recreating a particular state of your app. <figure class="highlight"> <pre><code class="language-r" data-lang="r"><span class="n">make_router</span><span class="p">(</span>  <span class="n">route</span><span class="p">(</span><span class="s2">"&lt;your_app_url&gt;/main"</span><span class="p">,</span>  <span class="n">main_page_shiny_ui</span><span class="p">),</span>  <span class="n">route</span><span class="p">(</span><span class="s2">"&lt;your_app_url&gt;/other"</span><span class="p">,</span> <span class="n">other_page_shiny_ui</span><span class="p">)</span> <span class="p">)</span></code></pre> </figure> If you’re in a hurry just go directly to the project’s page: <a href="https://appsilon.github.io/shiny.router/" target="_blank" rel="noopener noreferrer">https://appsilon.github.io/shiny.router/ </a> <h2 id="benefits-of-routing">Benefits of routing</h2> Routing has been around in web frameworks for a while. Since this was something we were missing in Shiny so much we developed this package to simplify our development. <strong>Firstly,</strong> it’s possible to share a link like <span style="text-decoration: underline;">http://your-app-url/stats/dashboard</span> and redirect a user to the specific state in-app. For instance, in our <a href="https://demo.appsilon.com/apps/router2/" target="_blank" rel="noopener noreferrer">shiny.router demo</a>, you can directly go to another page. <strong>Secondly,</strong> it’s easier to write clean code by separating UI into meaningful code blocks. <h2 id="how-do-you-integrate-it">How do you integrate it?</h2> First, make sure you have <strong>shiny.router</strong> dependency installed. This package is not yet available on CRAN, so you have to install it with <a href="https://github.com/hadley/devtools" target="_blank" rel="noopener noreferrer"><strong>devtools</strong></a>: <figure class="highlight"> <pre><code class="language-r" data-lang="r"><span class="c1"># install.packages("devtools") </span><span class="n">devtools</span><span class="o">::</span><span class="n">install_github</span><span class="p">(</span><span class="s2">"Appsilon/shiny.router"</span><span class="p">)</span></code></pre> </figure> Second, you have to define a routing. <figure class="highlight"> <pre><code class="language-r" data-lang="r"><span class="c1"># Creates router. We provide routing path and UI for this page. </span><span class="n">router</span> <span class="o">&lt;-</span> <span class="n">make_router</span><span class="p">(</span>  <span class="n">route</span><span class="p">(</span><span class="s2">"/"</span><span class="p">,</span> <span class="n">root_page</span><span class="p">),</span>  <span class="n">route</span><span class="p">(</span><span class="s2">"/other"</span><span class="p">,</span> <span class="n">other_page</span><span class="p">)</span> <span class="p">)</span></code></pre> </figure> This will create 2 reactive links: <ol><li><span style="text-decoration: underline;">http://your-app-url</span> redirecting to the <strong>Root page</strong> and</li><li><span style="text-decoration: underline;">http://your-app-url/other</span> redirecting to <b>Other pages</b> in your app.</li></ol> The first passed argument is also a default redirection for all invalid links(“/” in this case). You can also specify it explicitly via the <strong>“default”</strong> argument. <figure class="highlight"> <pre><code class="language-r" data-lang="r"><span class="c1"># Creates router. We provide routing path and UI for this page. </span><span class="n">router</span> <span class="o">&lt;-</span> <span class="n">make_router</span><span class="p">(</span>  <span class="n">default</span> <span class="o">=</span> <span class="n">route</span><span class="p">(</span><span class="s2">"/home"</span><span class="p">,</span> <span class="n">home_page</span><span class="p">),</span>  <span class="n">route</span><span class="p">(</span><span class="s2">"/"</span><span class="p">,</span> <span class="n">root_page</span><span class="p">),</span>  <span class="n">route</span><span class="p">(</span><span class="s2">"/other"</span><span class="p">,</span> <span class="n">other_page</span><span class="p">)</span> <span class="p">)</span></code></pre> </figure> Next, make sure you bind and run your <strong>“router”</strong> object properly in your Shiny app source code. <figure class="highlight"> <pre><code class="language-r" data-lang="r"><span class="c1"># Creat output for our router in main UI of Shiny app. </span><span class="n">ui</span> <span class="o">&lt;-</span> <span class="n">shinyUI</span><span class="p">(</span><span class="n">fluidPage</span><span class="p">(</span>    <span class="c1"># This line is important! </span>  <span class="n">router_ui</span><span class="p">()</span> <span class="p">))</span> <br><span class="c1"># Plug router into Shiny server. </span><span class="n">server</span> <span class="o">&lt;-</span> <span class="n">shinyServer</span><span class="p">(</span><span class="k">function</span><span class="p">(</span><span class="n">input</span><span class="p">,</span> <span class="n">output</span><span class="p">)</span> <span class="p">{</span>    <span class="c1"># This line is important! </span>  <span class="n">router</span><span class="p">(</span><span class="n">input</span><span class="p">,</span> <span class="n">output</span><span class="p">)</span> <span class="p">})</span></code></pre> </figure> Now it’s time for a live demo. Try clicking “Page” and “Other” menu links: <iframe src="https://demo.appsilon.com/apps/router2/_w_3f10f846/#!/" width="100%" height="250" frameborder="0" scrolling="no"></iframe> Here’s the complete code, if you want to try it out by yourself: <figure class="highlight"> <pre><code class="language-r" data-lang="r"><span class="n">library</span><span class="p">(</span><span class="n">shiny</span><span class="p">)</span> <span class="c1">#devtools::install_github("Appsilon/shiny.router") </span><span class="n">library</span><span class="p">(</span><span class="n">shiny.router</span><span class="p">)</span> <br><span class="c1"># This generates menu in user interface with links. </span><span class="n">menu</span> <span class="o">&lt;-</span> <span class="p">(</span>  <span class="n">tags</span><span class="o">$</span><span class="n">ul</span><span class="p">(</span>    <span class="n">tags</span><span class="o">$</span><span class="n">li</span><span class="p">(</span><span class="n">a</span><span class="p">(</span><span class="n">class</span> <span class="o">=</span> <span class="s2">"item"</span><span class="p">,</span> <span class="n">href</span> <span class="o">=</span> <span class="s2">"/"</span><span class="p">,</span> <span class="s2">"Page"</span><span class="p">)),</span>    <span class="n">tags</span><span class="o">$</span><span class="n">li</span><span class="p">(</span><span class="n">a</span><span class="p">(</span><span class="n">class</span> <span class="o">=</span> <span class="s2">"item"</span><span class="p">,</span> <span class="n">href</span> <span class="o">=</span> <span class="s2">"/other"</span><span class="p">,</span> <span class="s2">"Other"</span><span class="p">))</span>  <span class="p">)</span> <span class="p">)</span> <br><span class="c1"># This creates UI for each page. </span><span class="n">page</span> <span class="o">&lt;-</span> <span class="k">function</span><span class="p">(</span><span class="n">title</span><span class="p">,</span> <span class="n">content</span><span class="p">)</span> <span class="p">{</span>  <span class="n">div</span><span class="p">(</span>    <span class="n">menu</span><span class="p">,</span>    <span class="n">titlePanel</span><span class="p">(</span><span class="n">title</span><span class="p">),</span>    <span class="n">p</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>  <span class="p">)</span> <span class="p">}</span> <br><span class="c1"># Both sample pages. </span><span class="n">root_page</span> <span class="o">&lt;-</span> <span class="n">page</span><span class="p">(</span><span class="s2">"Home page"</span><span class="p">,</span> <span class="s2">"Welcome on sample routing page!"</span><span class="p">)</span> <span class="n">other_page</span> <span class="o">&lt;-</span> <span class="n">page</span><span class="p">(</span><span class="s2">"Some other page"</span><span class="p">,</span> <span class="s2">"Lorem ipsum dolor sit amet"</span><span class="p">)</span> <br><span class="c1"># Creates router. We provide routing path and UI for this page. </span><span class="n">router</span> <span class="o">&lt;-</span> <span class="n">make_router</span><span class="p">(</span>  <span class="n">route</span><span class="p">(</span><span class="s2">"/"</span><span class="p">,</span> <span class="n">root_page</span><span class="p">),</span>  <span class="n">route</span><span class="p">(</span><span class="s2">"/other"</span><span class="p">,</span> <span class="n">other_page</span><span class="p">)</span> <span class="p">)</span> <br><span class="c1"># Creat output for our router in main UI of Shiny app. </span><span class="n">ui</span> <span class="o">&lt;-</span> <span class="n">shinyUI</span><span class="p">(</span><span class="n">fluidPage</span><span class="p">(</span>  <span class="n">router_ui</span><span class="p">()</span> <span class="p">))</span> <br><span class="c1"># Plug router into Shiny server. </span><span class="n">server</span> <span class="o">&lt;-</span> <span class="n">shinyServer</span><span class="p">(</span><span class="k">function</span><span class="p">(</span><span class="n">input</span><span class="p">,</span> <span class="n">output</span><span class="p">)</span> <span class="p">{</span>  <span class="n">router</span><span class="p">(</span><span class="n">input</span><span class="p">,</span> <span class="n">output</span><span class="p">)</span> <span class="p">})</span> <br><span class="c1"># Run server in a standard way. </span><span class="n">shinyApp</span><span class="p">(</span><span class="n">ui</span><span class="p">,</span> <span class="n">server</span><span class="p">)</span></code></pre> </figure> <h2 id="next-steps">Next steps</h2> You might be wondering how we managed to make this nice-looking demo. This is a small preview of our next package using <a href="https://demo.appsilon.com/apps/visuarisk/" target="_blank" rel="noopener noreferrer"><strong>SemanticUI</strong></a>. You can find it on our <a href="https://github.com/Appsilon/shiny.semantic" target="_blank" rel="noopener noreferrer"><strong>Github</strong></a>. <strong>Side Note!</strong> <em>You will have to install it to run a second repo example.</em> Please stay tuned for our next blog post.

Have questions or insights?

Engage with experts, share ideas and take your data journey to the next level!

Is Your Software GxP Compliant?

Download a checklist designed for clinical managers in data departments to make sure that software meets requirements for FDA and EMA submissions.
Explore Possibilities

Share Your Data Goals with Us

From advanced analytics to platform development and pharma consulting, we craft solutions tailored to your needs.

Talk to our Experts
open source
tutorials
shiny dashboards