{"componentChunkName":"component---src-components-tutorials-js","path":"/tutorials/data-editor/","result":{"data":{"markdownRemark":{"html":"<h2>Contents</h2>\n<ol>\n<li><a href=\"#about\">Why would I need this?</a></li>\n<li>\n<p><a href=\"#work\">How does the app work?</a></p>\n<ol>\n<li><a href=\"#work-features\">Defining the features</a></li>\n<li><a href=\"#work-ui\">Building the UI</a></li>\n<li>\n<p><a href=\"#work-server\">Building the server</a></p>\n<ol>\n<li><a href=\"#work-server-loaddata\">Loading data</a></li>\n<li><a href=\"#work-server-defaults\">Application Defaults</a></li>\n<li><a href=\"work-server-view\">Events for View and Cancel</a></li>\n<li><a href=\"#work-server-editing\">Editing mode</a></li>\n<li><a href=\"#work-server-saving\">Saving data</a></li>\n</ol>\n</li>\n</ol>\n</li>\n<li><a href=\"#data-editor-run\">How can I run the demo?</a></li>\n</ol>\n<!-- endexcerpt -->\n<span id=\"about\"/>\n<h2>Why would I need this?</h2>\n<p>I created this example in response to a question that I had while working on a project: \"How can I edit a dataset in a shiny app?\"</p>\n<p>Editing data in a shiny application would be pretty useful as the changes could automatically be reflected in the visualizations, text, or other elements. This would also eliminate the need for editing values using other tools and duplicating files.  </p>\n<p>In this tutorial, we will create a data editor shiny application using the rhandsonpackage.</p>\n<span id=\"work\" />\n<h2>How does the app work?</h2>\n<p>To get the shiny app running, we will develop our application step-by-step. First, we build our UI and then write then server code to handle all of the features we want in our app. </p>\n<p>In this example, we will using a subset of the <a href=\"https://data.cityofnewyork.us/Health/NYC-Dog-Licensing-Dataset/nu7n-tubp\">NYC Dog Licensing Dataset</a>. I randomly pulled 100 rows from the file. See the script <code>data_0_source.R</code> in the <code>scripts/</code> folder for the code. I did not include the full dataset as it's quite large. Use the link above to download the file and adjust the script as necessary.</p>\n<span id=\"work-features\" />\n<h3>Defining the features</h3>\n<p>To start off, we should make a list of things we want the application to do. For example, when we load the application, what do we want to see first?</p>\n<ol>\n<li><strong>viewer</strong>: When the app loads, it would be nice to display the data in a table. We probably do not want to encourage users to edit data right away, but have it as a feature. In your application, it might be a good idea to create user groups to control who can edit data.</li>\n<li><strong>editor</strong>: Since the data will be displayed as view only by default, it would be nice to have something that starts the editing mode. A button would be perfect for this.</li>\n<li><strong>cancel</strong>: A cancel feature would be perfect for this application. For example, if a user enters the wrong information or decides not to edit data, then it would be useful to have a way to discard the changes and exit the editing mode.</li>\n<li><strong>save</strong>: Most importantly, we will need an option that saves our data. We might also want to archive previous versions in the event we need to undo changes.</li>\n<li><strong>refresh</strong>: Once the changes have been saved, we will need to refresh the application so the changes can be reflected in the table.</li>\n</ol>\n<p>For now, we will focus on these items. This list gives us some basic features for our designing the interface.</p>\n<span id=\"work-ui\" />\n<h3>Building the UI</h3>\n<p>Using the list of features, let's figure out how to structure the interface. Since we five key actions in our app (view, edit, cancel, save, and refresh), we can use buttons as we want to trigger events on demand. The buttons should be positioned in a \"settings panel\" and then the main area of the app should display the data table. </p>\n<p>The best option for the layout would be the <code>sidebarLayout</code>. This would allow us to put all the buttons in the <code>sidebarPanel</code> and render the table in the <code>mainPanel</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"r\"><pre class=\"language-r\"><code class=\"language-r\">ui <span class=\"token operator\">&lt;-</span> fluidPage<span class=\"token punctuation\">(</span>\n\n    <span class=\"token comment\"># use shinyjs</span>\n    shinyjs<span class=\"token operator\">::</span>useShinyjs<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n\n    <span class=\"token comment\"># app title</span>\n    titlePanel<span class=\"token punctuation\">(</span><span class=\"token string\">\"Data Editor\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n\n    <span class=\"token comment\"># main layout</span>\n    sidebarLayout<span class=\"token punctuation\">(</span>\n\n        <span class=\"token comment\"># sidebar</span>\n        sidebarPanel<span class=\"token punctuation\">(</span>\n            helpText<span class=\"token punctuation\">(</span><span class=\"token string\">\"What would you like to do?\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n            \n            <span class=\"token comment\"># buttons: view, edit, cancel, save, refresh</span>\n            actionButton<span class=\"token punctuation\">(</span><span class=\"token string\">\"view\"</span><span class=\"token punctuation\">,</span>label <span class=\"token operator\">=</span> <span class=\"token string\">\"view\"</span><span class=\"token punctuation\">,</span> icon<span class=\"token operator\">=</span>icon<span class=\"token punctuation\">(</span><span class=\"token string\">\"binoculars\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n            actionButton<span class=\"token punctuation\">(</span><span class=\"token string\">\"edit\"</span><span class=\"token punctuation\">,</span>label <span class=\"token operator\">=</span> <span class=\"token string\">\"edit\"</span><span class=\"token punctuation\">,</span> icon<span class=\"token operator\">=</span>icon<span class=\"token punctuation\">(</span><span class=\"token string\">\"pencil\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n            shinyjs<span class=\"token operator\">::</span>hidden<span class=\"token punctuation\">(</span>\n                actionButton<span class=\"token punctuation\">(</span><span class=\"token string\">\"cancel\"</span><span class=\"token punctuation\">,</span> label <span class=\"token operator\">=</span> <span class=\"token string\">\"cancel\"</span><span class=\"token punctuation\">,</span> icon<span class=\"token operator\">=</span>icon<span class=\"token punctuation\">(</span><span class=\"token string\">\"times\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                actionButton<span class=\"token punctuation\">(</span><span class=\"token string\">\"save\"</span><span class=\"token punctuation\">,</span> label <span class=\"token operator\">=</span> <span class=\"token string\">\"save\"</span><span class=\"token punctuation\">,</span> icon<span class=\"token operator\">=</span>icon<span class=\"token punctuation\">(</span><span class=\"token string\">\"save\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                actionButton<span class=\"token punctuation\">(</span><span class=\"token string\">\"refresh\"</span><span class=\"token punctuation\">,</span> label <span class=\"token operator\">=</span> <span class=\"token string\">\"refresh\"</span><span class=\"token punctuation\">,</span> icon <span class=\"token operator\">=</span> icon<span class=\"token punctuation\">(</span><span class=\"token string\">\"refresh\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n\n        <span class=\"token comment\"># main panel</span>\n        mainPanel<span class=\"token punctuation\">(</span>\n            tags<span class=\"token operator\">$</span>h2<span class=\"token punctuation\">(</span>textOutput<span class=\"token punctuation\">(</span><span class=\"token string\">\"helperText\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n            DT<span class=\"token operator\">::</span>dataTableOutput<span class=\"token punctuation\">(</span><span class=\"token string\">\"dt_view\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n            rhandsontable<span class=\"token operator\">::</span>rHandsontableOutput<span class=\"token punctuation\">(</span><span class=\"token string\">\"dt_edit\"</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span></code></pre></div>\n<p>It's important to note the use of <code>shinyjs::hidden</code>. When the application loads, cancel, save and refresh only apply to the editing mode. We will hide these buttons by default and show them as necessary.</p>\n<p>In the main panel, there are two table outputs: one for <code>DT</code> and one for the <code>rhandsontable</code> output. In the server, we will use the shinyjs package to hide and show the tables. There's likely a better way to render the tables, but for now, this will help us get the application running.</p>\n<p>Take at look at the heading.</p>\n<div class=\"gatsby-highlight\" data-language=\"r\"><pre class=\"language-r\"><code class=\"language-r\">tags<span class=\"token operator\">$</span>h2<span class=\"token punctuation\">(</span>textOutput<span class=\"token punctuation\">(</span><span class=\"token string\">\"helperText\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The header will receive text output from the server. We will update the text depending on the current mode the user is in (i.e., viewer or editor).</p>\n<p>We will also create two prompts, or modals using the shinyBS package. The first modal will be triggered when the save button is clicked and will ask the user, \"are you sure you want to save the changes?\". If the user clicks yes, then the save function will run. Once the file is saved, a confirmation message will appear (all changes were saved) and prompting you to refresh the app to view the changes. I'll put these before the <code>titlePanel</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"r\"><pre class=\"language-r\"><code class=\"language-r\"><span class=\"token comment\"># dialogue box: 'Are you sure you want to save changes?'</span>\nbsModal<span class=\"token punctuation\">(</span>id <span class=\"token operator\">=</span> <span class=\"token string\">\"savePrompt\"</span><span class=\"token punctuation\">,</span>  title <span class=\"token operator\">=</span> <span class=\"token string\">\"Do you want to save changes?\"</span><span class=\"token punctuation\">,</span> trigger <span class=\"token operator\">=</span><span class=\"token string\">\"save\"</span><span class=\"token punctuation\">,</span>  size <span class=\"token operator\">=</span> <span class=\"token string\">\"small\"</span><span class=\"token punctuation\">,</span>\n    wellPanel<span class=\"token punctuation\">(</span>    \n        helpText<span class=\"token punctuation\">(</span><span class=\"token string\">\"Saving will overwrite existing data! This cannot be undone.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        actionButton<span class=\"token punctuation\">(</span>inputId <span class=\"token operator\">=</span> <span class=\"token string\">\"no\"</span><span class=\"token punctuation\">,</span> label <span class=\"token operator\">=</span>  <span class=\"token string\">\"No\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        actionButton<span class=\"token punctuation\">(</span>inputId <span class=\"token operator\">=</span> <span class=\"token string\">\"yes\"</span><span class=\"token punctuation\">,</span>label <span class=\"token operator\">=</span> <span class=\"token string\">\"Yes\"</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                \n<span class=\"token comment\"># dialogue box: 'Changes were saved'</span>\nbsModal<span class=\"token punctuation\">(</span>id <span class=\"token operator\">=</span> <span class=\"token string\">\"saveSuccess\"</span><span class=\"token punctuation\">,</span> title <span class=\"token operator\">=</span> <span class=\"token string\">\"Save was successful!\"</span><span class=\"token punctuation\">,</span> trigger <span class=\"token operator\">=</span> <span class=\"token string\">\"yes\"</span><span class=\"token punctuation\">,</span> size <span class=\"token operator\">=</span> <span class=\"token string\">\"small\"</span><span class=\"token punctuation\">,</span>\n    wellPanel<span class=\"token punctuation\">(</span>\n        helpText<span class=\"token punctuation\">(</span><span class=\"token string\">\"Changes were saved successfully. Refresh the page for changes to take effect.\"</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span>\n<span class=\"token ellipsis\">...</span></code></pre></div>\n<span id=\"work-server\" />\n<h3>Building the server</h3>\n<p>In the shiny server server, we will define five elements.</p>\n<ol>\n<li><code>load the data</code>: You can source data using a file input widget, from a repository, or a database. In this example, we will use the file located in the data folder.</li>\n<li><code>defaults</code>: We will need to define the application defaults such as setting the default view for the table, titles, and other variables that we will use in the server.</li>\n<li><code>view</code> and <code>cancel</code>: To simply things, we will create a single event that resets the app to view mode when the view button or cancel button is clicked.</li>\n<li><code>edit</code>: When the edit button is clicked, this will render the dataset as an editable table and start watching for changes. We will also update the ui by hiding and showing buttons and updating the title to \"edit mode\".</li>\n<li><code>save</code>: Lastly, we when the user is finished making changes, we will run some code to archive the pre-changed data and save the edited data as the new master file.</li>\n</ol>\n<span id=\"work-server-loaddata\" />\n<h4>Load data</h4>\n<p>In this example, I'm using a subset of the dataset <a href=\"https://data.cityofnewyork.us/Health/NYC-Dog-Licensing-Dataset/nu7n-tubp\">NYC Dog Licensing Dataset</a> which I saved to an rds file. </p>\n<div class=\"gatsby-highlight\" data-language=\"r\"><pre class=\"language-r\"><code class=\"language-r\">nycDogs <span class=\"token operator\">&lt;-</span> readRDS<span class=\"token punctuation\">(</span><span class=\"token string\">\"data/nyc_dogs.RDS\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The reason I mention this is that this application uses the file as the source of truth and will write changes to this file. By default, the pre-changed data is timestamped and archived in the <code>data/archived/</code> folder. We will revisit this a little bit later.</p>\n<span id=\"work-server-defaults\" />\n<h4>Application Defaults</h4>\n<p>Next, we will set the defaults for the application. We will set the default mode (view mode) for the data table and update the title. In addition, we will initiate the reactive object for the changes in editor mode and define the event for page refresh.</p>\n<div class=\"gatsby-highlight\" data-language=\"r\"><pre class=\"language-r\"><code class=\"language-r\"><span class=\"token comment\"># orientation text: mode - view vs edit</span>\noutput<span class=\"token operator\">$</span>helperText <span class=\"token operator\">&lt;-</span> renderText<span class=\"token punctuation\">(</span><span class=\"token string\">\"View Mode\"</span><span class=\"token punctuation\">)</span>\n    \n<span class=\"token comment\"># datatable default render</span>\noutput<span class=\"token operator\">$</span>dt_view <span class=\"token operator\">&lt;-</span> DT<span class=\"token operator\">::</span>renderDataTable<span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n        DT<span class=\"token operator\">::</span>datatable<span class=\"token punctuation\">(</span>nycDogs<span class=\"token punctuation\">,</span> selection<span class=\"token operator\">=</span><span class=\"token string\">\"none\"</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    \n<span class=\"token comment\"># initiate values for edits</span>\nvalues <span class=\"token operator\">&lt;-</span> reactiveValues<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    \n<span class=\"token comment\"># define refresh</span>\nobserveEvent<span class=\"token punctuation\">(</span>input<span class=\"token operator\">$</span>refresh<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n    shinyjs<span class=\"token operator\">::</span>runjs<span class=\"token punctuation\">(</span><span class=\"token string\">\"history.go(0)\"</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<span id=\"work-server-view\" />\n<h4>Events for View and Cancel</h4>\n<p>In the app, we want to give the user the change to exit the editor and go back to the viewer. In the ui, the two buttons <code>view</code> and <code>cancel</code> will be used to trigger this behavior. To make things easier, we can create one event for both buttons. This event will exit the editor and display the normal data table. We will also hide the save and cancel buttons as we are no longer in editing mode.</p>\n<div class=\"gatsby-highlight\" data-language=\"r\"><pre class=\"language-r\"><code class=\"language-r\">observeEvent<span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    input<span class=\"token operator\">$</span>view\n    input<span class=\"token operator\">$</span>cancel\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span><span class=\"token punctuation\">{</span>\n    shinyjs<span class=\"token operator\">::</span>show<span class=\"token punctuation\">(</span><span class=\"token string\">\"view\"</span><span class=\"token punctuation\">)</span>\n    shinyjs<span class=\"token operator\">::</span>show<span class=\"token punctuation\">(</span><span class=\"token string\">\"edit\"</span><span class=\"token punctuation\">)</span>\n    shinyjs<span class=\"token operator\">::</span>hide<span class=\"token punctuation\">(</span><span class=\"token string\">\"cancel\"</span><span class=\"token punctuation\">)</span>\n    shinyjs<span class=\"token operator\">::</span>hide<span class=\"token punctuation\">(</span><span class=\"token string\">\"save\"</span><span class=\"token punctuation\">)</span>\n    shinyjs<span class=\"token operator\">::</span>show<span class=\"token punctuation\">(</span><span class=\"token string\">\"dt_view\"</span><span class=\"token punctuation\">)</span>\n    shinyjs<span class=\"token operator\">::</span>hide<span class=\"token punctuation\">(</span><span class=\"token string\">\"dt_edit\"</span><span class=\"token punctuation\">)</span>\n        \n    <span class=\"token comment\"># modifying header text</span>\n    output<span class=\"token operator\">$</span>helperText <span class=\"token operator\">&lt;-</span> renderText<span class=\"token punctuation\">(</span><span class=\"token string\">\"View Mode\"</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token ellipsis\">...</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span></code></pre></div>\n<span id=\"work-server-editing\" />\n<h4>Editing mode</h4>\n<p>Let's focus on the editing mode. First, we will remove the normal data table and show the rhandsontable output, as well as display the save and cancel buttons. We will also update the title to inform the user that there are in editing mode.</p>\n<div class=\"gatsby-highlight\" data-language=\"r\"><pre class=\"language-r\"><code class=\"language-r\">observeEvent<span class=\"token punctuation\">(</span>input<span class=\"token operator\">$</span>edit<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n    shinyjs<span class=\"token operator\">::</span>hide<span class=\"token punctuation\">(</span><span class=\"token string\">\"view\"</span><span class=\"token punctuation\">)</span>\n    shinyjs<span class=\"token operator\">::</span>hide<span class=\"token punctuation\">(</span><span class=\"token string\">\"edit\"</span><span class=\"token punctuation\">)</span>\n    shinyjs<span class=\"token operator\">::</span>show<span class=\"token punctuation\">(</span><span class=\"token string\">\"cancel\"</span><span class=\"token punctuation\">)</span>\n    shinyjs<span class=\"token operator\">::</span>show<span class=\"token punctuation\">(</span><span class=\"token string\">\"save\"</span><span class=\"token punctuation\">)</span>\n    shinyjs<span class=\"token operator\">::</span>hide<span class=\"token punctuation\">(</span><span class=\"token string\">\"dt_view\"</span><span class=\"token punctuation\">)</span>\n    shinyjs<span class=\"token operator\">::</span>show<span class=\"token punctuation\">(</span><span class=\"token string\">\"dt_edit\"</span><span class=\"token punctuation\">)</span>\n    \n    <span class=\"token comment\"># update the helperText: \"You are now in edit mode\"</span>\n    output<span class=\"token operator\">$</span>helperText <span class=\"token operator\">&lt;-</span> renderText<span class=\"token punctuation\">(</span><span class=\"token string\">\"Edit Mode\"</span><span class=\"token punctuation\">)</span>\n    <span class=\"token ellipsis\">...</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The following code allows us to make changes and directly render the changes in the ui. It also stores the changes into our reactive object values. We will use this object in the render function and send the output to the UI.</p>\n<div class=\"gatsby-highlight\" data-language=\"r\"><pre class=\"language-r\"><code class=\"language-r\"><span class=\"token comment\"># set reactive object for rhandsontable output</span>\ndata <span class=\"token operator\">&lt;-</span> reactive<span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>is.null<span class=\"token punctuation\">(</span>input<span class=\"token operator\">$</span>dt_edit<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n        DF <span class=\"token operator\">=</span> hot_to_r<span class=\"token punctuation\">(</span>input<span class=\"token operator\">$</span>dt_edit<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span>is.null<span class=\"token punctuation\">(</span>values<span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"DF\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n            DF <span class=\"token operator\">=</span> data.frame<span class=\"token punctuation\">(</span>nycDogs<span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n            DF <span class=\"token operator\">=</span> values<span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"DF\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n    \n    values<span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"DF\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> DF\n    DF\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token comment\"># render table</span>\noutput<span class=\"token operator\">$</span>dt_edit <span class=\"token operator\">&lt;-</span> rhandsontable<span class=\"token operator\">::</span>renderRHandsontable<span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    DF <span class=\"token operator\">=</span> data<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>is.null<span class=\"token punctuation\">(</span>DF<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n        rhandsontable<span class=\"token punctuation\">(</span>DF<span class=\"token punctuation\">,</span> stretchH <span class=\"token operator\">=</span> <span class=\"token string\">\"all\"</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<span id=\"work-server-saving\" />\n<h4>Saving data</h4>\n<p>Before we write the data, it would be useful to save a backup of the master file - just in case we need to undo something or for validation. Since we want to save the data after the user has been prompted and has selected \"yes\", we will wrap this an event for <code>input$yes</code>. We do not need an event for <code>save</code> as the <code>shinyBS</code> package handles the opening and closing of prompts. We will also hide the save and cancel buttons and display the refresh button.</p>\n<div class=\"gatsby-highlight\" data-language=\"r\"><pre class=\"language-r\"><code class=\"language-r\"><span class=\"token comment\"># When yes is clicked, save data as RDS</span>\nobserveEvent<span class=\"token punctuation\">(</span>input<span class=\"token operator\">$</span>yes<span class=\"token punctuation\">,</span><span class=\"token punctuation\">{</span>\n        \n    <span class=\"token comment\"># close popup </span>\n    toggleModal<span class=\"token punctuation\">(</span>session<span class=\"token punctuation\">,</span> modalId <span class=\"token operator\">=</span> <span class=\"token string\">\"savePrompt\"</span><span class=\"token punctuation\">,</span> toggle <span class=\"token operator\">=</span> <span class=\"token string\">\"close\"</span><span class=\"token punctuation\">)</span>\n        \n    <span class=\"token comment\"># closing: hide save buttons</span>\n    shinyjs<span class=\"token operator\">::</span>hide<span class=\"token punctuation\">(</span><span class=\"token string\">\"save\"</span><span class=\"token punctuation\">)</span>\n    shinyjs<span class=\"token operator\">::</span>hide<span class=\"token punctuation\">(</span><span class=\"token string\">\"cancel\"</span><span class=\"token punctuation\">)</span>\n    shinyjs<span class=\"token operator\">::</span>show<span class=\"token punctuation\">(</span><span class=\"token string\">\"refresh\"</span><span class=\"token punctuation\">)</span>\n    \n    <span class=\"token comment\"># save to RDS, but backup previous versions</span>\n    <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span>file.exists<span class=\"token punctuation\">(</span> <span class=\"token string\">\"data/nyc_dogs.RDS\"</span> <span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n\n        <span class=\"token comment\"># c = file prefix &amp; date &amp; RDS</span>\n        file.rename<span class=\"token punctuation\">(</span>\n            from <span class=\"token operator\">=</span> <span class=\"token string\">\"data/nyc_dogs.RDS\"</span><span class=\"token punctuation\">,</span>\n            to <span class=\"token operator\">=</span> paste0<span class=\"token punctuation\">(</span><span class=\"token string\">\"data/archive/nyc_dogs_\"</span><span class=\"token punctuation\">,</span>format<span class=\"token punctuation\">(</span>Sys.time<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span><span class=\"token string\">\"%Y%m%d-%H%M%S\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span><span class=\"token string\">\".RDS\"</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">)</span>\n\n        <span class=\"token comment\"># replace base file name with latest version</span>\n        saveRDS<span class=\"token punctuation\">(</span>out<span class=\"token punctuation\">,</span> <span class=\"token string\">\"data/nyc_dogs.RDS\"</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span><span class=\"token punctuation\">{</span>\n        saveRDS<span class=\"token punctuation\">(</span>out<span class=\"token punctuation\">,</span> <span class=\"token string\">\"data/nyc_dogs.RDS\"</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Once the save event runs, the user will receive a notification saying that the file was saved and will inform the user to refresh the page. When the page is refreshed, the master file will be reloaded and the previous version will be uneffected as it is now stored in the archive folder.</p>\n<p>That is it! Run the app and edit the data.</p>\n<span id=\"data-editor-run\" />\n<h2>How can I run the demo?</h2>\n<p>The source code is available on <a href=\"https://github.com/davidruvolo51/shinyAppTutorials/tree/master/Data-Editor\">github</a>. Alternatively, you can run the demo in R using the following code.</p>\n<div class=\"gatsby-highlight\" data-language=\"r\"><pre class=\"language-r\"><code class=\"language-r\">install.packages<span class=\"token punctuation\">(</span><span class=\"token string\">\"shiny\"</span><span class=\"token punctuation\">)</span>\nshiny<span class=\"token operator\">::</span>runGitHub<span class=\"token punctuation\">(</span>repo<span class=\"token operator\">=</span><span class=\"token string\">\"shinyAppTutorials\"</span><span class=\"token punctuation\">,</span>username<span class=\"token operator\">=</span><span class=\"token string\">\"davidruvolo51\"</span><span class=\"token punctuation\">,</span> subdir<span class=\"token operator\">=</span><span class=\"token string\">\"Data-Editor\"</span><span class=\"token punctuation\">)</span></code></pre></div>","frontmatter":{"title":"Data Editor","subtitle":"A shiny app for editing data in a shiny app","abstract":"Have you ever wanted to edit data in a shiny app? Learn how to build a shiny app for editing data and saving changes to file, and then reloading the changes into your app.","date":"2018-03-01","updated":"2019-11-21","keywords":["rhandsontable"]},"fields":{"readingTime":{"minutes":9.175}}}},"pageContext":{"slug":"/tutorials/data-editor/"}},"staticQueryHashes":["63159454"]}