Issues I am having couple of issues with (a) Display the data in interactive mode using Rshiny (2) Querying the results from mongodb Query. My codes are given below, it seems to work as independent pieces but doesnt coalesce well.
For Problem (a), I have previously used Output$values and that seems to work. Commented out in the code
For Problem (b), I have used mongolite R package to query the data and used reactive for passing the query.
library(data.table)
library(tidyverse)
library(shiny)
library(mongolite)
epi <- read.csv("./data/Genes.csv", header=T)
label = "gene"
epilist <- data.frame(epi$gene, label)
names(epilist) = c("value", "label")
df <- read.table("./data/CCLE_meta.csv", header=TRUE, sep=",", na.strings="NA", fill=TRUE)
dd <- data.frame((df$Tissue))
names(dd) = "Tissue"
cell1= dd %>% add_row(Tissue = "all")
label = "Tissue"
cell <- data.frame(cell1$Tissue, label)
names(cell) = c("value", "label")
ui <- fluidPage(
titlePanel("Dependencies for EpiGenes"),
sidebarLayout(
sidebarPanel(
selectizeInput("epiInput","gene", choices=NULL, selected=NULL),
selectizeInput("cellInput","Tissue", choices=NULL, selected=NULL),
textOutput("values")
),
mainPanel(
tabsetPanel(type = "tabs",
tabPanel("Fusions", tableOutput("table")),
tabPanel("CancerGD", tableOutput("table")),
tabPanel("CCLEmeta", tableOutput("table")),
tabPanel("EpiGenes", tableOutput("table"))
)
)
)
)
server <- function(input, output, session) {
updateSelectizeInput(session, 'epiInput',
choices = epilist$value,
server = TRUE)
updateSelectizeInput(session, 'cellInput',
choices = cell$value,
server = TRUE)
#output$values <- renderText({
# paste(input$epiInput, input$cellInput)
#})
### Looking into Epi Genes
con1 <- mongo(collection = "Genes", db = "discovery", url = "mongodb://127.0.0.1:27017")
data.for.table1 <- reactive({
query.foo <- paste0('{"gene" : epiInput}')
con1$find(query = query.foo, limit = 100)
})
output$EpiGenes <- renderDataTable({
data.for.table1()
})
### Looking into Cell Line Metadata
con0 <- mongo(collection = "CellLine", db = "discovery", url = "mongodb://127.0.0.1:27017")
data.for.table0 <- reactive({
query.foo <- paste0('{"Tissue" : input$cellInput}')
con0$find(query = query.foo, limit = 100)
})
output$CCLEmeta <- renderDataTable({
data.for.table0()
})
### Looking into fusion genes
con2 <- mongo(collection = "fusions", db = "discovery", url = "mongodb://127.0.0.1:27017")
data.for.table2 <- reactive({
query.foo <- paste0('{"gene" : input$epiInput}')
con2$find(query = query.foo, limit = 100)
})
output$Fusions <- renderDataTable({
data.for.table2()
})
### Looking into CancerGD
con3 <- mongo(collection = "CancerGD", db = "discovery", url = "mongodb://127.0.0.1:27017")
data.for.table3 <- reactive({
query.foo <- paste0('{"gene" : input$epiInput}')
con3$find(query = query.foo, limit = 100)
})
output$CancerGD <- renderDataTable({
data.for.table3()
})
# Automatically disconnect when connection is removed
rm(con0)
rm(con1)
rm(con2)
rm(con3)
gc()
}
shinyApp(ui, server)
The first expected output is an app to allow users to query from the list of genes and tissue. The second expected output is display query results in its appropriate tab (From 4 collections from database discovery). The current result is an app with no ability to query.
I was able to make some changes to the code and the error/hanging I now get is
"Imported 0 records. Simplifying into dataframe..."
Any insight into the error will be helpful.
The improvements to the codes are as follows;
(a) SidebarPanel
selectizeInput("epiInput","gene", choices=gg),
selectizeInput("cellInput","Tissue", choices=cc),
(b) Connecting to MongoDB
con2 <- mongo(collection="fusions", db="discovery", url="mongodb://localhost:27017", verbose = TRUE)
fusResults <- reactive({
region <- list(gene = input$epiInput)
query.foo <- paste0('{ "gene" : "',region , '"}')
fs <- con2$find(query = query.foo, limit = 100)
return(fs)
})
output$fus_results <- renderDataTable({
fusResults()
})
Related
Trying to work through an example to edit DT tables as shown here. Not sure my code is updating server-side as I'm hoping. I'm computing a mean of a variable just to see if things are being updated. I'm using renderUI as my real world problem is outputting more than just a table.
Thank you for any suggestions on how to get the table to update server side.
library(shiny)
library(DT)
bp <- data.frame(weights = rep(1,5), x = rnorm(5))
shinyApp(
ui = fluidPage(
#DT::dataTableOutput("x5"),
uiOutput("x5"),
verbatimTextOutput('test')
),
server = function(input, output, session) {
bp <- bp
output$x5 <- renderUI({
tableOut <- DT::datatable(bp, editable = TRUE, filter = list(position = 'bottom'))
})
# edit a single cell
proxy = dataTableProxy('x5')
observeEvent(input$x5_cell_edit, {
info = input$x5_cell_edit
bp <- editData(bp, info)
replaceData(proxy, bp, resetPaging = FALSE)
})
output$test <- renderPrint({
mean(bp$weights)
})
}
)
I'm trying to set up a ShinyApp which can access to a PostGreSQL/PostGIS database and perform reactive queries according to user inputs via selectInput widget.
I succeed to perform it with single inputs following this example (https://www.cybertec-postgresql.com/en/visualizing-data-in-postgresql-with-r-shiny/). My working code (sorry for non reprex example, but I cannont provide my database login for security purpose).
pool <- dbPool(drv = dbDriver("PostgreSQL", max.con = 100), user = "user", password = "pswd", host = "000.000.00.000", port = 5432, dbname = "db_name", idleTimeout = 3600000)
typology <- dbGetQuery(pool, "SELECT type FROM table GROUP BY type")
all_typo <- sort(unique(typology$type))
area_agripag <- dbGetQuery(pool, "SELECT area_name FROM table GROUP BY area_name")
all_area <- sort(unique(area_agripag$area_name))
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput(
inputId = "area",
label = "Select a district",
choices = all_area,
selected = 'district_1',
multiple = FALSE,
selectize = FALSE
),
selectInput(
inputId = "typo",
label = "Select a type",
choices = all_typo,
selected = 'type1',
multiple = FALSE,
selectize = FALSE
)
),
mainPanel(
tabsetPanel(
tabPanel("graph", plotOutput("plot")),
tabPanel("Table", dataTableOutput("table"))
)
)
)
)
server <- function(input, output, session) {
selectedData <- reactive({
req(input$area)
req(input$typo)
query <- sqlInterpolate(ANSI(),
"SELECT year, SUM(surface)
FROM table
WHERE area_name = ?area_name
AND type = ?type
GROUP BY year;",
area_name = input$area, type = input$typo)
outp <- as.data.frame(dbGetQuery(pool, query))
})
output$table <- DT::renderDataTable({
DT::datatable( data = selectedData(),
options = list(pageLength = 14),
rownames = FALSE)
})
output$plot <- renderPlot({
ggplot( data = selectedData(), aes(x = year, y = sum)) + geom_point()
})
}
shinyApp(ui = ui, server = server)
What I want to do is editing the reactive query in the server part in order to allow multiple selectInput. I should add IN operator instead of = in the sql query :
selectedData <- reactive({
req(input$area)
req(input$typo)
query <- sqlInterpolate(ANSI(),
"SELECT year, SUM(surface)
FROM table
WHERE area_name IN (?area_names)
AND type IN (?types)
GROUP BY year;",
area_names = input$area, types = input$typo)
outp <- as.data.frame(dbGetQuery(pool, query))
})
Next I know I should format the area_names / types vector returned by a multiple selectInput with some automatic regular expression. I want to wrap each elements of the vector with '', in order to accord with the SQL syntax.
For example, I want to transfrom the following multiple input$area vector :
area1 area2 area3
to
'area1', 'area2', 'area3'
In order to store it in the area_names sqlInterpolate argument.
Anyone has an idea how to perform this? Thanks to all contributions.
I print the output as textOutput, but i guess you can pick up the idea for whatever you want for :-)
#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30),
selectizeInput("mult", label = "Chooose", choices = c("area1", "area2", "area3"), selected = "area1", multiple = TRUE)
),
# Show a plot of the generated distribution
mainPanel(
textOutput("text")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$text <- renderText({
output <- ""
print(length(input$mult))
for(i in 1:length(input$mult)) {
if(i == length(input$mult)) {
output <- paste0(output, "'", input$mult[[i]], "'")
} else {
output <- paste0(output, "'", input$mult[[i]], "', ")
}
}
output
})
}
# Run the application
shinyApp(ui = ui, server = server)
Explanation: The input$multis a vector which lengths depends on how many inputs are selected. I initialize an empty output and start the loop.
paste0 will convert the input to a string and add a comma, except for the last iteration, where we do not want a comma. The double brackets extract the value by indexing. Hope this gets clear below:
x <- c(3,5,7)
paste0(x[[1]], " and ", x[[2]], " and ", x[[3]])
1] "3 and 5 and 7"
The [[i]] will change its value every iteration. Check out this to get a feeling for it.
https://www.r-bloggers.com/how-to-write-the-first-for-loop-in-r/
At the end, we just return the final string :-)
So after 2 days I figured out the problem. The mistake was sticking to sqlInterpolate for creating the SQL query. Using some renderPrint function to visualize the generated query, I noticed that some inopportune double quote was showing up in my query.
It appears that sqlInterpolate have been created to prevent security breach trough sql injection attacks (https://shiny.rstudio.com/articles/sql-injections.html), not allowing to use multiple input.
Thanks to parameterized queries (https://db.rstudio.com/best-practices/run-queries-safely) I was able to implement multiple in the query using sql_glue function.
Here are the usefull links for next ones :
glue documentation (https://glue.tidyverse.org/reference/glue_sql.html)
some similar topic (https://community.rstudio.com/t/using-multiple-r-variables-in-sql-chunk/2940/13)
similar with dbQuoteIdentifier function (How to use dynamic values while executing SQL scripts in R)
And the final code :
library(RPostgreSQL)
library(gdal)
library(leaflet)
library(shiny)
library(tidyverse)
library(sp)
library(rgeos)
library(rgdal)
library(DT)
library(knitr)
library(raster)
library(sf)
library(postGIStools)
library(rpostgis)
library(shinydashboard)
library(zip)
library(pool)
library(rjson)
library(reprex)
library(glue)
pool <- dbPool(drv = dbDriver("PostgreSQL", max.con = 100), user = "username", password = "pswd", host = "000.000.00.000", port = 5432, dbname = "database", idleTimeout = 3600000)
typology <- dbGetQuery(pool, "SELECT type FROM table GROUP BY type")
all_typo <- sort(unique(typology$type))
area_table <- dbGetQuery(pool, "SELECT area FROM tableGROUP BY area")
all_area <- sort(unique(area_table$area ))
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput(
inputId = "area",
label = "Select a district",
choices = all_area,
selected = 'area1',
multiple = TRUE,
selectize = FALSE
),
selectInput(
inputId = "typo",
label = "Select a type",
choices = all_typo,
selected = 'type1',
multiple = TRUE,
selectize = FALSE
)
),
mainPanel(
tabsetPanel(
tabPanel("graph", plotOutput("plot")),
tabPanel("Table", dataTableOutput("table"))
)
)
)
)
server <- function(input, output, session) {
selectedData <- reactive({
req(input$area)
req(input$typo)
query <- glue::glue_sql(
"SELECT year, SUM(surface)
FROM table
WHERE area IN ({area_name*})
AND type IN ({type*})
GROUP BY year;",
area_name = input$area,
type = input$typo,
.con = pool)
outp <- as.data.frame(dbGetQuery(pool, query))
outp
})
output$table <- DT::renderDataTable({
DT::datatable( data = selectedData(),
options = list(pageLength = 14),
rownames = FALSE)
})
output$plot <- renderPlot({
ggplot( data = selectedData(), aes(x = year, y = sum)) + geom_point()
})
}
shinyApp(ui = ui, server = server)
People!
If i have the following data frame:
observeEvent(input$pesquisa,{
query <- glue(
"select
cod_ordem_producao as ORDEM,
dim_ext_tubo as DIAMETRO,
esp_par_tubo as PAREDE,
cod_aqa as AQA,
tmo_ciclo_plan as CICLO,
dth_criacao_reg as DATA,
dsc_aco as GRAU,
val_lim_escoamento as LE,
val_tensao_residual as TR
from
QT_QTS.PLA_ORDEM_PRODUCAO
where DIM_EXT_TUBO = {as.numeric(input$diametro)}
and esp_par_tubo = {as.numeric(input$parede)}
and tmo_ciclo_plan = {as.numeric(input$ciclo)}
and dth_criacao_reg between DATE '{as.character(input$dates[1])}' and DATE '{as.character(input$dates[2])}'
and VAL_LIM_ESCOAMENTO != 0
order by DTH_CRIACAO_REG desc")
df <- dbGetQuery(
connection_reportUser,
query
)
df <-------------- HERE IS THE SAVED VALUES TO THE DATA FRAME---------------
valor_grau <- df$GRAU
})
And, next, I use another observeEvent:
observeEvent(input$pesquisa, {
insertUI(
selector = "#pesquisa",
where = "afterEnd",
ui = selectInput(
"grau",
label = "Grau:",
choices = valor_grau
)
)
})
Explaining:
I search in a database these values and save into a data.frame (called "df") . When I search for it (with the input's and clicking on the button "pesquisa"), a new field called "Grau:" appear for the user, with new selectable values.
How can I update the "df" with the value from the second input? (in that case, the input from the "insertUI" called "Grau:"
---------------- EDITED ------------------------
In my UI code, i have a: DT::dataTableOutput("contents2")
In server side, i have:
output$contents2 = DT::renderDataTable({
tabela_saida})
My first observeEvent is that described above, and save into my df, than, i have a:
tabela_saida = df
The second observeEvent, should update a value called GRAU in my tabela_saida.
The third observEvent, should update AQA...and so on.
The last of all, should expose the datable updated with all the new values and make a search in my database.
I think you want to update your data.frame according to an entry (grau). To do this, you can create an eventReactive that will execute your query. Within eventReactive you need to check if the user has already selected something in input$grau.
This is a way to do this:
library(shiny)
library(DT)
ui <- fluidPage(
mainPanel(
actionButton(inputId = "pesquisa", label = "pesquisa"),
conditionalPanel(condition = "input.pesquisa > 0", uiOutput("grau")),
DT::DTOutput("contents2")
)
)
server <- function(input, output) {
create_df <- eventReactive(input$pesquisa,{
## Your query about here
## ...
##
df <- data.frame(x = round(rnorm(100), 2), grau = rpois(100, lambda = 10))
grau_values <- unique(df$grau)
if(!is.null(input$grau)){
grau_input <- input$grau
df <- subset(df, grau %in% grau_input)
}
return(list(df = df, grau_values = grau_values))
})
output$grau <- renderUI({
grau_values <- create_df()$grau_values
selectInput(inputId = "grau", label = "Grau:", multiple = TRUE, choices = grau_values, selected = NULL)
})
output$contents2 <- DT::renderDataTable({
df <- create_df()$df
datatable(df, rownames = FALSE)
})
}
shinyApp(ui = ui, server = server)
I hope it works!
i worked on data from SQL Server in R using RODBC and after getting my result i created ShinyApp to deploy my result But i want to get my data from my SQL query directly without exporting my result to Excel and then import it to shiny,How can i do that?
Test <- odbcDriverConnect("driver={SQL Server};server=localhost;database=Fakahany;trusted_connection=true")
Orders<- sqlQuery(Test,"
SELECT
WHWorkOrderHeaderId
, OtherLangDescription
FROM Warehouse.WHWorkOrderDetails
INNER JOIN Warehouse.WHWorkOrderHeader AS WHH
ON Warehouse.WHWorkOrderDetails.WHWorkOrderHeaderId = WHH.ID
INNER JOIN Warehouse.StockItems
ON Warehouse.WHWorkOrderDetails.StockItemId = Warehouse.StockItems.Id
WHERE Type = 'IO'
ORDER BY OtherLangDescription ASC")
#Creating the correlations
Orders$OtherLangDescription <- as.factor(Orders$OtherLangDescription)
orderList <- unique(Orders$OtherLangDescription)
ListId <- lapply(orderList, function(x) subset(Orders, OtherLangDescription == x)$WHWorkOrderHeaderId)
Initial_Tab <- lapply(ListId, function(x) subset(Orders, WHWorkOrderHeaderId %in% x)$OtherLangDescription)
Correlation_Tab <- mapply(function(Product, ID) table(Product)/length(ID),
Initial_Tab, ListId)
colnames(Correlation_Tab) <- orderList
cor_per<- round(Correlation_Tab*100,2)
DF<-data.frame(row=rownames(cor_per)[row(cor_per)], col=colnames(cor_per)[col(cor_per)], corr=c(cor_per))
and this is my app code:
#loading Packages
library(RODBC)
library(shiny)
library(rsconnect)
ui <- fluidPage(
titlePanel("Item Correlation"),
sidebarPanel(
selectInput("Item2","Select Item",choices= DF$FirstItem),
h6("Powerd By:"),
img(src='edrak.png',height='50px',width='110px')
# ,selectInput("Item","SelectItem",choices= DF$col)
),
mainPanel(
tableOutput("Itemcorr")
)
)
server <- function(input,output){
output$Itemcorr <- renderTable({
subset(DF, DF$FirstItem == input$Item2)
})
}
shinyApp(ui, server)
This should do what you want.
library(RODBCext)
library(shiny)
ui <- shinyUI(
pageWithSidebar(
headerPanel("Hide Side Bar example"),
sidebarPanel(
textInput("CATEGORY", "Enter CATEGORY below"),
submitButton(text="Submit")
),
mainPanel(
tabsetPanel(
tabPanel("Data", tableOutput("tbTable"))
)
)
)
)
server <- function(input, output, session)
{ # NOTE THE BRACE HERE
myData <- reactive({
req(input$CATEGORY)
#connect to database
dbhandle = odbcDriverConnect('driver={SQL Server};server=Server_Name;database=Database_Name;trusted_connection=true')
#build query
query = "SELECT * FROM [Your_Table] where [CATEGORY] = ?"
#store results
res <- sqlExecute(channel = dbhandle,
query = query,
data = list(input$CATEGORY),
fetch = TRUE,
stringsAsFactors = FALSE)
#close the connection
odbcClose(dbhandle)
#return results
res
})
output$tbTable <-
renderTable(myData())
} # AND NOTE THE CLOSING BRACE HERE
shinyApp(ui = ui, server = server)
You may want to consider this as well.
library(shiny)
library(RODBCext)
shinyApp(
ui =
shinyUI(
fluidPage(
uiOutput("select_category"),
tableOutput("display_data")
# plotOutput("plot_data")
)
),
# server needs the function; looks ok
server = shinyServer(function(input, output, session)
{
# A reactive object to get the query. This lets you use
# the data in multiple locations (plots, tables, etc) without
# having to perform the query in each output slot.
QueriedData <- reactive({
req(input$showDrop)
ch <- odbcDriverConnect("driver={SQL Server};server=Server_Name;database=DATABASE_NAME;trusted_connection=true")
showList <- sqlExecute(ch, "SELECT * FROM [Your_Table] WHERE Category = ?",
data = list(Category = input$showDrop),
fetch = TRUE,
stringsAsFactors = FALSE)
odbcClose(ch)
showList
})
# The select input control. These can be managed dynamically
# from the server, and then the control send back to the UI
# using `renderUI`
output$select_category <- renderUI({
ch <- odbcDriverConnect("driver={SQL Server};server=Server_Name;database=DATABASE_NAME;trusted_connection=true")
showList <- sqlExecute(ch, "Select Distinct Category From [Your_Table] Order by Category",
fetch = TRUE,
stringsAsFactors = FALSE)
odbcClose(ch)
selectInput(inputId = "showDrop",
label = "Select Asset",
showList$Category)
})
# Display the data in a table
output$display_data <- renderTable({
QueriedData()
})
# Display a plot
# output$plot_data <-
# renderPlot({
# plot(QueriedData()) # fill in the plot code you want to use.
# })
})
)
My R program works as expected. It shows a table containing my dataFrame, and lets me edit the values.
How do I capture those values and save them to my dataframe, or a copy of my dataframe?
require(shiny)
library(rhandsontable)
DF = data.frame(val = 1:10, bool = TRUE, big = LETTERS[1:10],
small = letters[1:10],
dt = seq(from = Sys.Date(), by = "days", length.out = 10),
stringsAsFactors = F)
rhandsontable(DF, rowHeaders = NULL)
EDIT:
The above code produces a table with rows and columns. I can edit any of the rows and columns. But when I look at my dataFrame, those edits do not appear. What I am trying to figure out is what do I need to change so I can capture the new values that were edited.
I know this thread's been dead for years, but it's the first StackOverflow result on this problem.
With the help of this post - https://cxbonilla.github.io/2017-03-04-rhot-csv-edit/, I've come up with this:
library(shiny)
library(rhandsontable)
values <- list()
setHot <- function(x)
values[["hot"]] <<- x
DF <- data.frame(val = 1:10, bool = TRUE, big = LETTERS[1:10],
small = letters[1:10],
dt = seq(from = Sys.Date(), by = "days", length.out = 10),
stringsAsFactors = FALSE)
ui <- fluidPage(
rHandsontableOutput("hot"),
br(),
actionButton("saveBtn", "Save changes")
)
server <- function(input, output, session) {
observe({
input$saveBtn # update dataframe file each time the button is pressed
if (!is.null(values[["hot"]])) { # if there's a table input
DF <<- values$hot
}
})
observe({
if (!is.null(input$hot)){
DF <- (hot_to_r(input$hot))
setHot(DF)
}
})
output$hot <- renderRHandsontable({
rhandsontable(DF) %>% # actual rhandsontable object
hot_table(highlightCol = TRUE, highlightRow = TRUE, readOnly = TRUE) %>%
hot_col("big", readOnly = FALSE) %>%
hot_col("small", readOnly = FALSE)
})
}
shinyApp(ui = ui, server = server)
However, I don't like my solution on the part of DF <<- values$hot as I previously had problems with saving changes to the global environment. I've couldn't figure it out any other way, though.
It seems to be accessible now via input$NAME_OF_rHandsontableOutput and can be converted to a data.frame via hot_to_r().
Reproducible example:
library(shiny)
library(rhandsontable)
ui <- fluidPage(
rHandsontableOutput("hottable")
)
server <- function(input, output, session) {
observe({
print(hot_to_r(input$hottable))
})
output$hottable <- renderRHandsontable({
rhandsontable(mtcars)
})
}
shinyApp(ui, server)
I was able to accomplish this with a more simple solution for saving data while the app is open and after it is closed for shiny 1.7++
Create an observe event dependent upon a save button clicked at any point when the app is open. I've scaled this method in more complex apps where you have a selectizeinput for swapping in and out different data frames into the rhandsontable, each of which are edited, saved and recalled while the app is open.
In the server:
observeEvent(input$save, { #button is the name of the save button, change as needed
df <<- hot_to_r(input$rhandsontable) #replace rhandsontable with the name of your own
}) #df is the data frame that have it access when the app starts
In the UI:
actionButton("save","Save Edits")
I don't know what you want to recover exactly, but this seems to work:
DF <- rhandsontable(DF, rowHeaders = NULL)
library(jsonlite)
fromJSON(DF$x$data)
If you are using Shiny then input$table$changes$changes can give you the edited value with row and column index. Below is the code if you want to update only specific cell and not the complete table using hot_to_t().
library(shiny)
library(rhandsontable)
DF = data.frame(val = 1:10, bool = TRUE, big = LETTERS[1:10],
small = letters[1:10],
dt = seq(from = Sys.Date(), by = "days", length.out = 10),
stringsAsFactors = F)
ui <- fluidPage(
rHandsontableOutput('table')
)
server <- function(input, output) {
X = reactiveValues(data = DF)
output$table <- rhandsontable::renderRHandsontable({
rhandsontable(X$data, rowHeaders = NULL)
})
observeEvent(input$table$changes$changes,{
row = input$table$changes$changes[[1]][[1]]
col = input$table$changes$changes[[1]][[2]]
value = input$table$changes$changes[[1]][[4]]
X$data[row,col] = value
})
}
shinyApp(ui, server)
Here's an example from related post How to add columns to a data frame rendered with rhandsontable in R Shiny with an action button?, which started with Tonio Liebrand's solution above but rendered reactively with columns added by the user via action button so you can see the table evolve and see how manual edits to the table stick around:
library(shiny)
library(rhandsontable)
myDF <- data.frame(x = c(1, 2, 3))
ui <- fluidPage(rHandsontableOutput('hottable'),
br(),
actionButton('addCol', 'Add'))
server <- function(input, output, session) {
EmptyTbl <- reactiveVal(myDF)
observeEvent(input$hottable, {
EmptyTbl(hot_to_r(input$hottable))
})
output$hottable <- renderRHandsontable({
rhandsontable(EmptyTbl())
})
observeEvent(input$addCol, {
newCol <- data.frame(c(1, 2, 3))
names(newCol) <- paste("Col", ncol(hot_to_r(input$hottable)) + 1)
EmptyTbl(cbind(EmptyTbl(), newCol))
})
}
shinyApp(ui, server)