knitr::opts_chunk$set(echo = FALSE) readExample <- function(filename, from=NULL, to=NULL) { cont <- readLines(paste0('inst/examples/', filename)) if (!is.null(from)) { from <- grep(paste0('^# ', from, '\\. '), cont) from <- from[1] from <- from + 2 while (trimws(cont[from]) == '' && from < length(cont)) { from <- from + 1 } } else { from <- 1 } if (!is.null(to)) { to <- grep(paste0('^# ', to, '\\. '), cont) to <- to[1] to <- to - 2 while (trimws(cont[to]) == '' && to > 1) { to <- to - 1 } } else { to <- length(cont) } cont <- cont[seq.int(from, to)] cat('```\n') cat(cont, sep='\n') cat('```\n') }
crudtable is an R package that makes it easy to develop an editable data table in Shiny web applications. With crudtable, the following operations may be easily achieved:
See the live demo of the crudtable package.
To install the latest development version from GitHub:
install.packages("remotes") remotes::install_github("beerda/crudtable")
A minimal Shiny app that uses crudtable:
readExample('minimal/app.R')
First, a Data Access Object (DAO) is created with dataFrameDao
.
DAO is a list structure that provides data access functions to the crudTable
user interface.
In this example, a simple DAO is created that works with an in-memory data frame CO2
.
Alternatively, an SQL database may be connected with crudtable's sqlDao
DAO.
The UI part consists of crudTableUI
that uses
DT's DataTable
to view the dataset.
The crudtable UI also provides the New record, Edit record and Delete record buttons.
The server part consists of the call of the crudTable
module that connects the crudTableUI
with the DAO.
All the aspects and capabilities of the crudtable package will be shown in this advanced example, which covers:
First of all, let us import all the needed packages:
readExample('advanced/app.R', NULL, 1)
We need DBI
and RSQLite
for database access, and shinyjs
for JavaScript support.
Next, we initialize the in-memory SQLite database engine and register the connection cleanup hook on
stop of Shiny. We also create an empty data frame df
with columns: date
, service
,
amount
, discount
, total
and paid
. This data frame is saved into SQLite as table 'invoice'
.
We also create a Data Access Object (DAO) dao
by calling the sqlDao()
function:
readExample('advanced/app.R', 1, 2)
Note also the typecast
argument of the sqlDao()
call: it causes the internally numeric attribute
date
to be type casted into Date
. Such workaround is needed because the DBI interface does not
support such complex data types as Date
.
For our convenience, we also create a constant list of service prices that will be used to populate the select box with values:
readExample('advanced/app.R', 2, 3)
We also want a custom edit dialog window with some pre-defined values and well defined ranges for
numeric inputs. We also add two read only input lines that will present some computed values to
the user. For that, we use the disabled()
function of the shinyjs
package. Note also the
namespacing of the input IDs by the ns()
function, which is mandatory:
readExample('advanced/app.R', 3, 4)
After the edit form UI is defined, we need to create the server part of the form handler. Since
we want to perform a lot of custom functionality, we code the server part in two steps. First, a
default form server handler is initialized by calling the formServerFactory()
function:
readExample('advanced/app.R', 4, 5)
formServerFactory()
requires dao
and a definition of validators
. Validator is a mechanism
for restricting the input to certain criteria. If the user insert invalid input, an error message
is shown and the edit form dialog can not be submitted. In the piece of code above, we define two
types of validators: a custom validator bound to the amount
data input, which tests the oddness
of the value. The second validator is filledValidator
that ensures the data inputs are filled.
filledValidator
is bound to all data inputs - we call names(dao$getAttributes())
instead of
enumerating names of all data columns.
Now we can define our server-side handler of the edit form. First, defaultFormServer
handler
must be called, which returns a list of useful reactive values and triggers. After that, we can
provide an observer that computes the read only inputs of the form. Note that we need to observe
the res$loadTrigger()
here, which triggers everytime the data get loaded into the edit form.
This ensures that the computed values are initialized properly too. Note also that the server-side
handler must return the res
, which is the result of defaultFormServer
:
readExample('advanced/app.R', 5, 6)
And that's nearly all. The last step is the initialization of the Shiny app. We use crudTableUI
on the client side and we call the crudTableServer
function on the server side. The latter gets dao
,
myFormUI
and myFormServer
as arguments. Note also that the crudTableServer
function returns
a reactive value that changes everytime the CRUD table widget changes the data. That reactive value
can be used to trigger update of output widgets that rely on the data, as can be seen below.
readExample('advanced/app.R', 6, NULL)
Note that it is not needed to call the useShinyjs()
function in the UI of the Shiny application
since the crudtable package does it internally by itself.
The complete advanced example is as follows:
readExample('advanced/app.R')
Enjoy.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.