I am writing a Shiny app that will be deployed across various users with screen resolutions ranging from 720p to 1080p. The application will be deployed on the web.
My page has a simple sidebar and a main content area. In order to adjust the width of the sidebar (to contain all the contents without any scrolling), I used two conditionalPanels in my UI.r, which render the appropriate 1080p or 720p UIs by evaluating "screen.width > 1600" or "screen.width < 1600".
This works fine, and the appropriate UIs are rendered as required.
However, after profiling the application, I realized that while the appropriate UI panels were indeed displayed, my server code was rendering both the high resolution and low resolution outputs, even though only one is being displayed at any given time.
Is there any way to disable the output that is not being displayed? I was looking into using global variables, since the screen width is never going to change during a session, but I was having trouble with shinyjs and evaluating the "screen.width" expression--it seems to return NULL anywhere but inside a conditionalPanel
Thanks
Without a minimal reproducible example, providing a solution is difficult. But req or validate and need might be what you want.
req is used to check values exist prior to execution: req documentation.
validate and need can be used together in a very similar way: validate documentation.
For example, you might try:
output$my_1080_plot = renderPlot(
validate(need(screen.width > 1600, message = FALSE))
# other commands to make plot
)
If the logical condition is not met then evaluation ceases and the other command are not run.
Related
I am looking to get the values from a reactive function, based on a specific set of inputs, but without the dashboard open or visible. Is this possible?
I have two possible solutions, both of them I am not sure are possible, and which of the two would be better. Also, I do think there could be a better solution.
Start the dashboard at a specific time and write away a csv with the required information. I don't know how to put the input values to the right settings though (they would be different from the normal initial settings). Hopefully start this without a visible endpoint (headless chromedriver for example).
Within Shiny, do a check if it's a specific time. If that's the case, change all inputs to the right settings, and export/do something with the required values. I don't prefer this, as there will be users using the dashboard at that time, and I don't want to disturb their work.
To give a bit more context, I would like to obtain values/dataframes from several dashboards at a specific time. These values are calculated via a chain of multiple reactives and inputs. I cannot trust that these dashboards are already running, so I need to start them.
As described in RStudio reference docs,
shiny server functions can optionally include session as a parameter (e.g. function(input, output, session)). The session object is an environment that can be used to access information and functionality relating to the session.
I never use this parameter in my apps and could be missing something.
What are the practical uses of the session parameter?
Here is my attempt for an overview:
List of use cases:
Customised user interfaces
chat room
games
Javascript communication
Trigger a function when session is ended
global reactive values for modularised shiny apps
updating inputs
Trigger a function when session is ended
E.g. close a database connection, see
How to implement a cleanup routine in R Shiny?.
Stopping a shiny app when browser / session is closed:
How to stop running shiny app by closing the browser window?
Customising the user interface
The user interface will be dependent on the device from which its called.
Is it a mobile or pc, which screen resolution is used etc.
Using fluid pages in the ui will help, but certainly has there limits as well.
With session$clientData$output_{OUTPUT_ID}_height and session$clientData$output_{OUTPUT_ID}_width
you can track how your outputs are rendered for your user.
You could make live adjustments (dont insert my huge title if the plot is too small). Or you can track
the data and adjust your ui after finding the most common ui settings of your users.
User interactions
You can create a local/secret reactiveValue() within that session / for that user and you can set
reactiveValues() outside the server function for "global infos" that are accessible across users/sessions.
That way you can share infos across sessions, but also hide specific values for certain users.
Use Case example: Chat room
https://shiny.rstudio.com/gallery/chat-room.html
Use Case example: Games
Can R Shiny display different views for two simultaneous users, interacting with one another?
Share data between modules
As mentioned in the comment, there is a current open bounty where it is asked to have
global reactive values for modularised shiny apps.
See Shiny modules: Destroy module ui if server-function fails
and
https://appsilon.com/super-solutions-for-shiny-architecture-1-of-5-using-session-data/?nabe=4634331497365504:0.
Finally, there is Some functionality you indirectly use, since there are good wrapper functions / packages for that.
Sending messages to Javascript
(There are good wrappers for this. E.g. shinyjs package).
If you want to integrate javascript in your app and send a message from shiny to javascript you can do it with
session:sendCustomMessage().
See, e.g.
http://www.blog.rdata.lu/post/2017-09-16-communication-between-r-and-d3js/ and
https://shiny.rstudio.com/articles/js-send-message.html.
Updating inputs
You could use session$sendInputMessage(inputId, message) to update inputs.
But again there are already more convenient wrapper functions for this, e.g. updateTextInput().
But it´s interesting to keep in mind for inputs that dont have a helper function.
General overview:
https://shiny.rstudio.com/reference/shiny/latest/session.html
I have built a shiny dashboard which has a set of data loaded in as a data frame. It uses dplyr to then select columns, mutate new columns if needed, apply a set of filters and then plot using a variety of high-level ggplot2-based packages.
We try to do the data load, select and mutate just the once. The filtering is sat in a reactive variable, accessed by the plot, and is based upon different input values.
As far as I see this is a pretty standard and typical use case.
I'm wondering whether anyone could advise on workflow patterns to make the output more responsive.
There are two scenarios I encounter with this writing pattern which appear to cause significant user interface delay which I'd like to avoid:
Firstly, when the dashboard first loads it tries to plot the charts using NULL data. I've found I can get around this by using if(is.null(my_data_frame)) and returning geom_blank() rather than our plot. Is there a neater / faster way to do this?
Secondly (and more challengingly): to the right of my plot are a (potentially large) set of filter options to allow the user to analyse subsets. If the user clicks several of these options in rapid succession, Shiny will repeatedly recalculate our reactive() value and replot the chart for each click event: where the user actually just needed to set or clear 5 options. Is there a way to prevent this happening - so if the recalculation isn't complete we don't continue with the plot in progress as we've just made the data stale? Or do you think about grouping options with an update button to prevent this?
In response to your second bullet. Check out shiny's debounce/throttle capabilities. These should slow down the reactive response so your user can finish with the UI control before the chart or presentation element recalculates.
For your first question, try using the req function inside your reactive block. If your plot is waiting on the data frame to load, you can put the code for loading the data frame in a named reactive block (it seems like you may have already done this), then pass that to req. This will prevent the plot from attempting to render until it receives a valid value for whatever you passed to req.
For the second, I'd recommend wrapping your plot render in an observeEvent and having an 'Update' button, if you typically expect users to change multiple options between desired plot updates.
Finally, for added performance, I just saw today that Shiny v1.2.0 has either just been released or is about to be, the major feature of which is plot caching. You can find more details HERE.
First let's understand the app:
The sample app mocks grabbing data from 2 sources: an array of available objects, and an array of objects being used.
The app also displays new objects (available ones not being used).
Finally, it also allows you to use (register) one of the new objects
Requirements:
The app needs to display the list of New objects first
The app needs to minimize the number of API calls to the bare minimum and only make calls when strictly necessary
Calls to produce changes in API data (register) should be reactive and display changes in UI immediately
The code I have implemented meets these 3 requirements. However, I'm really unhappy with this implementation, and I'm sure that's not the way the Vuex store is supposed to be used.
For starters, my implementation only works for the specific order in which the components are displayed in the screen:
<new name="New" :selected="true"></new>
<available name="Available"></available>
<using name="Using"></using>
If I, for example, want to move <available> to the last tab, the code will break.
This happens because I haven't been able to simply call dispatch('getNews') once and have everything else fall into place, without at the same time duplicating one or to API calls, and thus not meeting the requirements...
I tried using dispatch('...').then().then() but I haven't been able to make it work and meet the requirements.
I would greatly appreciate anyone with experience in similar situations with Vuex tell me how they'd do this.
Bonus if you can do it without adding extra mutations.
I need to render multiple image or plot (whichever faster works for me) in Shiny web app. By multiple I mean about 1000+ image. I am trying to create a kind of dashboard of heat-o-meter gauges to show the status of a server whether it is in healthy condition or not. I am aware of how to render multiple image and plot in Shiny but to scale up to 1000+ and render them in a short amount of time is a challenge. Is there any way to do it in faster?
I have tried several methods such as:
creating multiple plots, putting them into list, and display them
using grid.arrange from gridExtra package. Problem here is
grid.arrange() takes a lot of time to render for 1000+ images.
creating multiple plot in 1 image, save them to png, and display the png file. Also same problem like grid.arrange() method. It takes a lot of time.
Render and save the plot for every servers beforehand in multiple image and display the image when any of the server is
called. Would like to know how esp for 1000+ image? and to render that many images I am afraid there
will be performance issue also.
Any other method? I am wondering if Shiny is able to pre-render all the plots once then let the users see it when they go into the Shiny web-app website. But that does not seem how Shiny works. The web-app process is re-started whenever user access the website.