<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/official-release-of-shiny-router-and-its-new-features/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://appsilon.com/shiny-router-package/"> r – Appsilon Data Science | We Provide End­ to­ End Data Science Solutions</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<blockquote>
<p><span>In a web application, routing is the process of using URLs to drive the user interface. Routing adds more possibilities and flexibility while building a complex and advanced web application, offering dividing app into separated sections.</span></p>
</blockquote>
<p><img alt="shiny.router routing" src="https://i1.wp.com/appsilon.com/wp-content/uploads/2018/09/1.gif?w=450" class="wp-image-1293" data-recalc-dims="1"></p>
<h1>New features</h1>
<p><span>Contributing to open source is incorporated into <a rel="nofollow" href="http://appsilon.com/company/" target="_blank">Appsilon mission</a>. Last week we <a rel="nofollow" href="http://appsilon.com/internationalization-of-shiny-apps-i18n/" target="_blank">updated i18n internationalization package</a>, now it’s time for shiny.router. Our </span><a rel="nofollow" href="https://github.com/Appsilon/shiny.router" target="_blank"><span>shiny.router</span></a><span> package provides you an easy solution how to add routing to your Shiny application. Since the <a rel="nofollow" href="https://appsilon.com/shiny-router-a-simple-routing-package-for-shiny/" target="_blank">last release</a> we managed to improve and add some great features to it. Find them on the list below!<br>
</span></p>
<h2><span>Routing moved fully to R assets</span></h2>
<p><span>Previously shiny.router was based on the external </span><a rel="nofollow" href="https://visionmedia.github.io/page.js/" target="_blank"><span>page.js</span></a><span> library. Thanks to the use of shiny session object we moved it fully to R.</span></p>
<h2><span>Separated server for each bookmark</span></h2>
<p><span>Now each bookmark can be isolated and fully working shiny app. The new feature allows you not only to separate UI for each bookmark – you may also define its own server now. Just check below example!</span></p>
<figure>
<pre><code data-lang="r"><span>library</span>(shiny)
<span>library</span>(shiny.router)

<span># This creates UI for each page.</span>
page &lt;- <span>function</span>(title, content) {
  div(
    titlePanel(title),
    p(content),
    uiOutput(<span>&quot;power_of_input&quot;</span>)
  )
}

<span># Part of both sample pages.</span>
home_page &lt;- page(<span>&quot;Home page&quot;</span>, <span>&quot;This is the home page!&quot;</span>)
side_page &lt;- page(<span>&quot;Side page&quot;</span>, <span>&quot;This is the side page!&quot;</span>)

<span># Callbacks on the server side for the sample pages</span>
home_server &lt;- <span>function</span>(input, output, session) {
  output$power_of_input &lt;- renderUI({
    HTML(paste(
      <span>&quot;I display <strong>square</strong> of input and pass result to <code>output$power_of_input</code>: &quot;</span>, 
      as.numeric(input$int) ^ <span>2</span>))
  })
}

side_server &lt;- <span>function</span>(input, output, session) {
  output$power_of_input &lt;- renderUI({
    HTML(paste(
      <span>&quot;I display <strong>cube</strong> of input and <strong>also</strong> pass result to <code>output$power_of_input</code>: &quot;</span>, 
      as.numeric(input$int) ^ <span>3</span>))
  })
}

<span># Create routing. We provide routing path, a UI as well as a server-side callback for each page.</span>
router &lt;- make_router(
  route(<span>&quot;home&quot;</span>, home_page, home_server),
  route(<span>&quot;side&quot;</span>, side_page, side_server)
)

<span># Create output for our router in main UI of Shiny app.</span>
ui &lt;- shinyUI(fluidPage(
  shiny::sliderInput(<span>&quot;int&quot;</span>, <span>&quot;Choose integer:&quot;</span>, -<span>10</span>, <span>10</span>, <span>1</span>, <span>1</span>),
  router_ui()
))

<span># Plug router into Shiny server.</span>
server &lt;- shinyServer(<span>function</span>(input, output, session) {
  router(input, output, session)
})

<span># Run server in a standard way.</span>
shinyApp(ui, server)</code></pre>
</figure>
<p><img alt="shiny.router - separate servers" src="https://i0.wp.com/appsilon.com/wp-content/uploads/2018/09/2.gif?w=450" class="wp-image-1299" data-recalc-dims="1"></p>
<h2>Pass parameters to an app using GET URL variables</h2>
<figure>
<pre><code data-lang="r"><span>library</span>(shiny)
<span>library</span>(shiny.router)

<span># Main page UI.</span>
home_page &lt;- div(
  titlePanel(<span>&quot;Home page&quot;</span>),
  p(<span>&quot;This is the home page!&quot;</span>),
  uiOutput(<span>&quot;power_of_input&quot;</span>)
)

<span># Creates routing. We provide routing path, a UI as well as a server-side callback for each page.</span>
router &lt;- make_router(
  route(<span>&quot;/&quot;</span>, home_page, <span>NA</span>)
)

<span># Create output for our router in main UI of Shiny app.</span>
ui &lt;- shinyUI(fluidPage(
  shiny::sliderInput(<span>&quot;int&quot;</span>, <span>&quot;Choose integer:&quot;</span>, -<span>10</span>, <span>10</span>, <span>1</span>, <span>1</span>),
  router_ui()
))

<span># Plug router into Shiny server.</span>
server &lt;- shinyServer(<span>function</span>(input, output, session) {
  router(input, output, session)
  
  component &lt;- reactive({
    <span>if</span> (is.null(get_query_param()$add)) {
      <span>return</span>(<span>0</span>)
    }
    as.numeric(get_query_param()$add)
  })
  
  output$power_of_input &lt;- renderUI({
    HTML(paste(
      <span>&quot;I display input increased by <code>add</code> GET parameter from app url and pass result to <code>output$power_of_input</code>: &quot;</span>, 
      as.numeric(input$int) + component()))
  })
})

<span># Run server in a standard way.</span>
shinyApp(ui, server)</code></pre>
</figure>
<p><img alt="shiny.router - passing get parameter" src="https://i0.wp.com/appsilon.com/wp-content/uploads/2018/09/3.gif?w=450" class="wp-image-1300" data-recalc-dims="1"></p>
<h2>Operate routing from the server side</h2>
<ul>
<li><code>route_link</code> – function for changing url for bookmark by adding hashbang (#!) prefix,</li>
<li><code>change_page</code> – function for changing the currently displayed page,</li>
<li><code>get_page</code> – function to extract “hash” part of the url,</li>
<li><code>is_page</code> – function that verifies if current page is was passed succesfuly.</li>
</ul>
<figure>
<pre><code data-lang="r"><span>library</span>(shiny)
<span>library</span>(shiny.router)

<span># This generates menu in user interface with links.</span>
menu &lt;- (
  tags$ul(
    tags$li(a(class = <span>&quot;item&quot;</span>, href = route_link(<span>&quot;home&quot;</span>), <span>&quot;Home page&quot;</span>)),
    tags$li(a(class = <span>&quot;item&quot;</span>, href = route_link(<span>&quot;side&quot;</span>), <span>&quot;Side page&quot;</span>))
  )
)

<span># This creates UI for each page.</span>
page &lt;- <span>function</span>(title, content) {
  div(
    menu,
    titlePanel(title),
    p(content),
    actionButton(<span>&quot;switch_page&quot;</span>, <span>&quot;Click to switch page!&quot;</span>)
  )
}

<span># Both sample pages.</span>
home_page &lt;- page(<span>&quot;Home page&quot;</span>, uiOutput(<span>&quot;current_page&quot;</span>))
side_page &lt;- page(<span>&quot;Side page&quot;</span>, uiOutput(<span>&quot;current_page&quot;</span>))

<span># Creates router. We provide routing path, a UI as</span>
<span># well as a server-side callback for each page.</span>
router &lt;- make_router(
  route(<span>&quot;home&quot;</span>, home_page, <span>NA</span>),
  route(<span>&quot;side&quot;</span>, side_page, <span>NA</span>)
)

<span># Create output for our router in main UI of Shiny app.</span>
ui &lt;- shinyUI(fluidPage(
  router_ui()
))

<span># Plug router into Shiny server.</span>
server &lt;- shinyServer(<span>function</span>(input, output, session) {
  router(input, output, session)
  
  output$current_page &lt;- renderText({
    page &lt;- get_page(session)
    sprintf(<span>&quot;Welcome on %s page!&quot;</span>, page)
  })
  
  observeEvent(input$switch_page, {
    <span>if</span> (is_page(<span>&quot;home&quot;</span>)) {
      change_page(<span>&quot;side&quot;</span>)
    } <span>else</span> <span>if</span> (is_page(<span>&quot;side&quot;</span>)) {
      change_page(<span>&quot;home&quot;</span>)
    }
  })
})

<span># Run server in a standard way.</span>
shinyApp(ui, server)</code></pre>
</figure>
<p><img src="https://i1.wp.com/appsilon.com/wp-content/uploads/2018/09/4.gif?resize=322%2C218" alt="shiny.router - navigation functions" width="322" class="wp-image-1301" data-recalc-dims="1" height="218"></p>
<h2><span>Styling – Bootstrap and Semantic UI<br>
</span></h2>
<p><span>You can suppress </span><a rel="nofollow" href="https://getbootstrap.com/" target="_blank"><span>Bootstrap</span></a><span> dependency on the specified bookmark. You can switch between Bootstrap and Semantic UI pages or disable styles. This is e</span><span>specially useful when using both Bootstrap and </span><a rel="nofollow" href="https://semantic-ui.com/" target="_blank"><span>semantic-UI</span></a><span> frameworks in one application.</span></p>
<p><span> </span></p>
<figure>
<pre><code data-lang="r">
<span>library</span>(shiny)
<span>library</span>(shiny.router)
<span>library</span>(shiny.semantic)

<span># Both sample pages.</span>
bootstrap_page &lt;- fluidPage(
  sidebarLayout(
    sidebarPanel(
      sliderInput(<span>&quot;obs_bootstrap&quot;</span>,
                  <span>NULL</span>,
                  min = <span>0</span>,
                  max = <span>100</span>,
                  value = <span>50</span>,
                  step = <span>1</span>)
    ),
    mainPanel(
      p(<span>&quot;Selected value:&quot;</span>),
      textOutput(<span>&quot;value_bootstrap&quot;</span>)
    )
  )
)

semanticui_page &lt;- semanticPage(
  slider_input(<span>&quot;obs_semantic&quot;</span>,
              min = <span>0</span>,
              max = <span>100</span>,
              value = <span>50</span>,
              step = <span>1</span>),
  p(<span>&quot;Selected value:&quot;</span>),
  textOutput(<span>&quot;value_semantic&quot;</span>)
)

<span># Creates router. We provide routing path, a UI as</span>
<span># well as a server-side callback for each page.</span>
router &lt;- make_router(
  route(<span>&quot;bootstrap&quot;</span>, bootstrap_page),
  route(<span>&quot;semantic&quot;</span>, semanticui_page),
  page_404 = page404(<span>&quot;You opened non existing bookmark!&quot;</span>)
)

<span># Create output for our router in main UI of Shiny app.</span>
ui &lt;- shinyUI(
  tagList(
    tags$head(
      singleton(disable_bootstrap_on_bookmark(<span>&quot;semantic&quot;</span>))
    ),
    router_ui()
  )
)

<span># Plug router into Shiny server.</span>
server &lt;- shinyServer(<span>function</span>(input, output, session) {
  router(input, output, session)
  output$value_bootstrap &lt;- renderText(input$obs_bootstrap)
  output$value_semantic &lt;- renderText(input$obs_semantic)
})

<span># Run server in a standard way.</span>
shinyApp(ui, server)</code></pre>
</figure>
<h1><img alt="shiny.router - more addins" src="https://i0.wp.com/appsilon.com/wp-content/uploads/2018/09/5.gif?w=450" class="wp-image-1302" data-recalc-dims="1"></h1>
<h1>How to get shiny.router?</h1>
<p>Shiny.router is available both on <a rel="nofollow" href="https://cran.r-project.org/web/packages/shiny.router/index.html" target="_blank">R Cran</a> and <a rel="nofollow" href="https://github.com/Appsilon/shiny.router" target="_blank">Github</a>. If you will stumble upon any issues please file them on GitHub where our team will reply. Are you using already shiny.router package in your shiny projects? <a rel="nofollow" href="mailto:hello@appsilon.com" target="_blank"><em><strong>Say hello</strong></em></a> to us and share your story – it will help us make our open source better.  Look for us on R events and collect our hex stickers!<br>
<img src="https://i1.wp.com/appsilon.com/wp-content/uploads/2018/09/RGB-electronic-version-05-e1537358166566.png?resize=250%2C289" alt="shiny.router hex sticker" width="250" class="wp-image-1303" data-recalc-dims="1" height="289"></p>
<p> </p>
<h1>Further steps and plans for the package</h1>
<p>We are planning to constantly work on the package to make it more versatile. As next steps we want to allow passing parameters between separated bookmarks servers and ability to save application state. We hope that you will appreciate improvements we did within last two years.</p>
<p>Feedback will be very valuable for us.</p>
<p>Artykuł <a rel="nofollow" href="https://appsilon.com/shiny-router-package/" target="_blank">Official release of shiny.router and its new features</a> pochodzi z serwisu <a rel="nofollow" href="https://appsilon.com/" target="_blank">Appsilon Data Science | We Provide End­ to­ End Data Science Solutions</a>.</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://appsilon.com/shiny-router-package/"> r – Appsilon Data Science | We Provide End­ to­ End Data Science Solutions</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/mPE-X0S12J4" height="1"></a></div>