I have a shiny app with a css style-sheet. Within the shiny app i use reactable and reactable.extras to capture text inputs.
library(shiny)
library(dplyr)
library(reactable)
library(reactable.extras)
df <- tibble(text_col = rep(NA, 5))
tweak_css <- function(file = "style.css") {
tags$link(rel= "stylesheet",
type = "text/css",
href = file) |>
tags$head()
}
shinyApp(
ui = fluidPage(
tweak_css(),
reactable_extras_dependency(),
reactableOutput("react"),
dataTableOutput("out")
),
server = function(input, output) {
rv <- reactiveValues(data = df)
output$react <- renderReactable({
reactable(
rv$data,
columns = list(
text_col = colDef(
cell = text_extra(id = "text",
class = "text-extra"))
)
)
})
text_d <- reactive({ input$text}) %>% debounce(3000)
observeEvent(text_d(), {
rv$data[text_d()$row, text_d()$column] <- text_d()$value
})
output$out <- renderDataTable({
rv$data
})
}
)
The accompanying style-sheet defines the size of the text input field. I fail to manage preventing text overflow.
.text-extra {
width: 80px;
height: 80px;
word-break: break-word;
}
I tried almost everything described here How to prevent text from overflowing in CSS? but it does not solve the problem. What can i do that the user can enter text with line breaks?
EDIT:
The use of DT seems not suitable since my original application has some more columns with checkboxes included.
I have a shiny app with a css style-sheet. Within the shiny app i use reactable and reactable.extras to capture text inputs.
library(shiny)
library(dplyr)
library(reactable)
library(reactable.extras)
df <- tibble(text_col = rep(NA, 5))
tweak_css <- function(file = "style.css") {
tags$link(rel= "stylesheet",
type = "text/css",
href = file) |>
tags$head()
}
shinyApp(
ui = fluidPage(
tweak_css(),
reactable_extras_dependency(),
reactableOutput("react"),
dataTableOutput("out")
),
server = function(input, output) {
rv <- reactiveValues(data = df)
output$react <- renderReactable({
reactable(
rv$data,
columns = list(
text_col = colDef(
cell = text_extra(id = "text",
class = "text-extra"))
)
)
})
text_d <- reactive({ input$text}) %>% debounce(3000)
observeEvent(text_d(), {
rv$data[text_d()$row, text_d()$column] <- text_d()$value
})
output$out <- renderDataTable({
rv$data
})
}
)
The accompanying style-sheet defines the size of the text input field. I fail to manage preventing text overflow.
.text-extra {
width: 80px;
height: 80px;
word-break: break-word;
}
I tried almost everything described here How to prevent text from overflowing in CSS? but it does not solve the problem. What can i do that the user can enter text with line breaks?
EDIT:
The use of DT seems not suitable since my original application has some more columns with checkboxes included.
Share Improve this question edited Feb 4 at 7:24 Philipp Schulz asked Feb 3 at 16:08 Philipp SchulzPhilipp Schulz 2032 silver badges9 bronze badges 01 Answer
Reset to default 1What can i do that the user can enter text with line breaks?
You could wrap the text_extra
function and give it the correct style.
Code
library(shiny)
library(dplyr)
library(reactable)
library(reactable.extras)
df <- tibble(text_col = rep(NA, 5))
# Custom text input function for reactable
text_extra <- function(id = NULL, class = NULL) {
function(value, index, name) {
div(
class = class,
style = "white-space: pre-wrap !important; word-break: break-all !important;",
tags$textarea(
id = paste0(id, "_", index),
class = "shiny-input-textarea form-control",
style = "width: 80px; height: 80px; resize: none;",
value
)
)
}
}
shinyApp(
ui = fluidPage(
reactable_extras_dependency(),
tags$head(
tags$script("
$(document).on('change', '.shiny-input-textarea', function() {
Shiny.setInputValue(this.id, this.value);
});
")
),
reactableOutput("react"),
dataTableOutput("out")
),
server = function(input, output, session) {
rv <- reactiveValues(data = df)
output$react <- renderReactable({
reactable(
rv$data,
columns = list(
text_col = colDef(
cell = text_extra(id = "text", class = "text-extra")
)
)
)
})
observe({
for(i in 1:nrow(rv$data)) {
local({
local_i <- i
input_id <- paste0("text_", local_i)
observeEvent(input[[input_id]], {
req(input[[input_id]])
rv$data$text_col[local_i] <- input[[input_id]]
print(paste("Updated row", local_i, "with value:", input[[input_id]])) # Debug print
}, ignoreInit = TRUE)
})
}
})
output$out <- renderDataTable({
rv$data
})
}
)
With datatable and checkboxes
library(shiny)
library(dplyr)
library(DT)
# Create sample data
df <- tibble(
text_col = rep(NA, 5),
yes_no = rep(FALSE, 5)
)
shinyApp(
ui = fluidPage(
DTOutput("table")
),
server = function(input, output, session) {
rv <- reactiveValues(data = df)
output$table <- renderDT({
datatable(
rv$data,
editable = list(
target = 'cell',
disable = list(columns = c(2)) # Enable editing for text column only
),
selection = "none",
options = list(
columnDefs = list(
list(
targets = 2, # yes_no column index (1-based)
render = JS("
function(data, type, row, meta) {
if (type === 'display') {
return '<input type=\"checkbox\"' +
(data ? ' checked' : '') +
' onclick=\"(' + function(el) {
var cell = el.parentNode;
var row = cell.parentNode;
var rowIdx = row.rowIndex;
var colIdx = cell.cellIndex;
Shiny.setInputValue(\'checkbox_click\',
{row: rowIdx, checked: el.checked, col: colIdx},
{priority: \'event\'}
);
} + ')(this)\">';
}
return data;
}")
)
)
)
)
})
observeEvent(input$table_cell_edit, {
info <- input$table_cell_edit
rv$data[info$row, info$col] <- info$value
})
observeEvent(input$checkbox_click, {
info <- input$checkbox_click
print(info)
rv$data$yes_no[info$row] <- info$checked # Add 1 because JS is 0-based
print(rv$data)
})
}
)