关键词:
【中文标题】分配/更改动态生成的 UI 组件的 div ID (R Shiny/Javascript)【英文标题】:Assign/change div ID of dynamically generated UI components (R Shiny/Javascript) 【发布时间】:2021-12-29 09:33:01 【问题描述】:我正在使用 uiOutput/renderUI 在 R 闪亮应用程序中动态生成几个表。这些表是可编辑的,因为它们呈现检索到的数据,然后用户可以更改这些数据并将其发送以进行进一步处理。我正在使用 rhandsontable,但理论上可以使用 DT、excelR 或任何其他表 - 但是它们都没有 ID 属性。 这就是现在呈现的页面的样子(对于 var3 中的每个新条目,都会呈现一个包含 3 个表的新流体行)
每个表格的标签都是唯一的,可以在表格创建期间用作标识符,就像我使用它在表格顶部创建标签一样。 如果我检查元素并查找表格的 div ID,我可以获取表格的内容。例如这里使用 input$outbd32eabbd01a4806 给了我数据。
但是,此 ID 在应用程序内部是未知的,并且表的数量是未知的。 如果我在创建时用一个已知 ID(例如 Sample2_Alpha)的 div 包装每个表,它会在此动态 div id 之上创建另一个 div 元素,但我仍然无法获取此表
我认为可能有几种方法可以解决这个问题,但我会想到以下方法。我不太熟悉 Javascript,但是这些都可能吗?
-
在创建动态表时分配 div ID?
这种方式,直接input$varName会给我表格内容(这里需要用hot_to_r(input$varName)读取)
如果我们用已知的 div ID 包装每个元素,那么该组件的子 div 呢?
在这种方法中,我可以维护每个已知 div 及其子 div 的矩阵,我可以使用它来检索数据,就像上面一样。
谢谢
library(shiny)
library(rhandsontable)
library(shinyWidgets)
ui <- fluidPage(
fluidRow(
uiOutput('test'),
actionBttn(
inputId = "Id107",
label = "button",
style = "unite",
color = "danger"
)
)
)
server <- function(input, output, session)
var1 <-c(1,2,3)
var2 <-c('X','Y','Z')
var3 <-c('Sample1','Sample2')
observeEvent(input$Id107,
#We should be able to get the input$ID of all dynamically generated tables here to retrieve any changes
browser()
)
output$test = renderUI(
table_names<-c('Alpha', 'Beta', 'Gamma')
t<- matrix(data = 0, nrow = length(var2), ncol = length(var1)) %>%
`rownames<-`(c(var2)) %>%
`colnames<-`(c(var1))
t1<-t
t2<-t
input_list <- lapply(1:length(var3), function(i)
new_list <- lapply(1:length(table_names),function(j) paste(var3[i] ," ", table_names[j], sep = "") )
list(
column(12,
column(5,align='left',withTags(div(h5(b(new_list[1]))))),
column(4,align='left',withTags(div(h5(b(new_list[2]))))),
column(3,align='left',withTags(div(h5(b(new_list[3]))))),
),
column(12,
column(5,div(id = gsub("[^[:alnum:]]", "_", new_list[1]),renderRHandsontable(
rhandsontable(t, overflow='hidden',maxRows=nrow(t), minRows=nrow(t)) %>%
hot_validate_numeric(c(1:ncol(t))) %>%
hot_table(stretchH = "all") %>%
hot_col(c(1:ncol(t)),format = "$0,0")))
),
column(4,div(id = gsub("[^[:alnum:]]", "_", new_list[2]),renderRHandsontable(#
rhandsontable(t1, overflow='hidden',maxRows=nrow(t1), minRows=nrow(t1)) %>%
hot_validate_numeric(c(1:ncol(t1))) %>%
hot_table(stretchH = "all") %>%
hot_col(c(1:ncol(t1)),format = "0.00%")))
),
column(3,div(id = gsub("[^[:alnum:]]", "_", new_list[3]),renderRHandsontable(#
rhandsontable(t2, overflow='hidden',maxRows=nrow(t2), minRows=nrow(t2)) %>%
hot_validate_numeric(c(1:ncol(t2))) %>%
hot_table(stretchH = "all") %>%
hot_col(c(1:ncol(t2)),format = "0")))
)
)
)
)
do.call(tagList,input_list)
)
shinyApp(ui, server)
【问题讨论】:
你为什么不使用更闪亮的方式,使用rHandsontableOutput
和renderRHandsontable
代替? renderUI
更静态。
我不知道如何使用 rHandsontableOutput 创建未知数量的表。以这种方式生成的每个表都不需要一个 output$ 占位符吗?我事先不知道我需要创建多少对象,因此我求助于 renderUI。如果你能分享一个 sn-p 会很有帮助
在 R 中访问list
的另一种方式是list[['item_name']]
,所以你可以使用output[['xx']] <- xxx
。换上lapply(tables, function(x)output[[x]] <- xxx )
。您无需担心范围界定。 Shiny 建立在R6
之上,为您处理父环境分配。否则你可以尝试使用do.call
。
谢谢-所以我将基本上遍历表(其名称是动态生成的),并通过在服务器端分配适当的renderRHandsontable
为每个这样的名称创建一个output[[table_name]]
列表?所以这很有意义。但是我对如何在 UI.R 中使用带有未知表名的rHandsontableOutput
有点困惑?还是我仍在使用renderUI/uiOutput
符号?抱歉,如果这很简单,但我是新手 - 如果你可以给我看一个只有一张桌子的例子,那真的会解开我的障碍 - 再次感谢你对此的投入
在下面查看我的帖子
【参考方案1】:
像这样:
一切都是从服务器动态生成的。
library(shiny)
library(rhandsontable)
# give me random 1 - 9 numbers of tables
n_tables <- sample(9, size = 1)
tablenames <- paste0("iris", seq(n_tables))
# for demo, I just use the same dataset repeatedly, but with different now numbers
table_content <- lapply(seq(n_tables), function(x) head(iris, n = x * 2))
names(table_content) <- tablenames
ui <- fluidPage(
uiOutput("tables"),
verbatimTextOutput("print_table")
)
server <- function(input, output, session)
output$tables <- renderUI(
tagList(
lapply(tablenames, function(x)
rHandsontableOutput(x)
),
selectInput("choose_tb", "get a table's value", choices = tablenames)
)
)
lapply(tablenames, function(x)
output[[x]] <- renderRHandsontable(rhandsontable(table_content[[x]]))
)
# to get the values
observeEvent(input$choose_tb,
req(input$choose_tb)
output$print_table <- renderPrint(
print(hot_to_r(input[[input$choose_tb]]))
)
, ignoreInit = TRUE)
shinyApp(ui, server)
好的,我考虑了你的方法,下面是 javascript 版本。基本上,按照您的要求,当您单击按钮时,它会向浏览器发送一个信号,并且浏览器会为您获取所有表 ID,并作为输入 table_ids
发送回 Shiny 中的 R。所以你只需要注意那个输入。确保更改#test
以匹配uiOutput('test')
的ID,#
是必需的。由于对JS不熟悉,不详述
library(shiny)
library(rhandsontable)
library(shinyWidgets)
getIds <- function(session)
session$sendCustomMessage("get_table_ids", list())
ui <- fluidPage(
fluidRow(
uiOutput('test'),
actionBttn(
inputId = "Id107",
label = "button",
style = "unite",
color = "danger"
)
),
tags$script(
'
Shiny.addCustomMessageHandler("get_table_ids", function(data)
let ids = $("#test .rhandsontable.html-widget").map(function()return $(this).prop("id")).get();
console.log(ids);
Shiny.setInputValue("table_ids", ids);
)
'
)
)
server <- function(input, output, session)
var1 <-c(1,2,3)
var2 <-c('X','Y','Z')
var3 <-c('Sample1','Sample2')
observeEvent(input$Id107,
getIds(session)
)
observe(
req(input$table_ids)
print(input$table_ids)
)
output$test = renderUI(
table_names<-c('Alpha', 'Beta', 'Gamma')
t<- matrix(data = 0, nrow = length(var2), ncol = length(var1)) %>%
`rownames<-`(c(var2)) %>%
`colnames<-`(c(var1))
t1<-t
t2<-t
input_list <- lapply(1:length(var3), function(i)
new_list <- lapply(1:length(table_names),function(j) paste(var3[i] ," ", table_names[j], sep = "") )
list(
column(12,
column(5,align='left',withTags(div(h5(b(new_list[1]))))),
column(4,align='left',withTags(div(h5(b(new_list[2]))))),
column(3,align='left',withTags(div(h5(b(new_list[3]))))),
),
column(12,
column(5,div(id = gsub("[^[:alnum:]]", "_", new_list[1]),renderRHandsontable(
rhandsontable(t, overflow='hidden',maxRows=nrow(t), minRows=nrow(t)) %>%
hot_validate_numeric(c(1:ncol(t))) %>%
hot_table(stretchH = "all") %>%
hot_col(c(1:ncol(t)),format = "$0,0")))
),
column(4,div(id = gsub("[^[:alnum:]]", "_", new_list[2]),renderRHandsontable(#
rhandsontable(t1, overflow='hidden',maxRows=nrow(t1), minRows=nrow(t1)) %>%
hot_validate_numeric(c(1:ncol(t1))) %>%
hot_table(stretchH = "all") %>%
hot_col(c(1:ncol(t1)),format = "0.00%")))
),
column(3,div(id = gsub("[^[:alnum:]]", "_", new_list[3]),renderRHandsontable(#
rhandsontable(t2, overflow='hidden',maxRows=nrow(t2), minRows=nrow(t2)) %>%
hot_validate_numeric(c(1:ncol(t2))) %>%
hot_table(stretchH = "all") %>%
hot_col(c(1:ncol(t2)),format = "0")))
)
)
)
)
do.call(tagList,input_list)
)
shinyApp(ui, server)
【讨论】:
你摇滚!谢谢好先生!我将使用您的第一种方法,以便更多地了解 R 的能力使用 javascript 访问动态生成的 HTML 元素的 id 时获取 null
...布时间】:2018-09-1107:46:44【问题描述】:我正在尝试动态更改div的ID并删除附加到父div的按钮。当用户单击ID为removeButton2的按钮时,我希望removeButt 查看详情
如何更改材质 UI 警报组件的类型?
...设置警报严重性时,我收到此错误“类型\'字符串\'不可分配给类型\'颜色|未定义\'。”我确实将类型设置为字符串,但是,我似乎无法弄清楚如 查看详情
javascript动态生成列表(获取点击列表的id)
我有一个div和ul代码如下:<divid="myDiv"> <ulid="myUl"> </ul></div>------------------------------------------------------------<scripttype="text/javaS 查看详情
如何动态更改没有 ID 的 MENU 文本
】如何动态更改没有ID的MENU文本【英文标题】:HowdoIdynamicchangeMENUtextwhichwithoutID【发布时间】:2013-11-2507:30:55【问题描述】:我尝试按照代码更改菜单文本,在命令窗口中显示正确的活动,更改菜单文本,但UI没有变化。另外,... 查看详情
当组件从父组件动态更改时调用子组件中的方法
】当组件从父组件动态更改时调用子组件中的方法【英文标题】:Invokemethodinchildcomponentwhenthecomponentischangeddynamicallyfromtheparentcomponent【发布时间】:2018-05-0414:03:32【问题描述】:我有一个简单的组件层次结构,其中有一个父组件... 查看详情
动态生成 ID 的选择器
】动态生成ID的选择器【英文标题】:SelectorfordynamicallygeneratedID【发布时间】:2011-06-1509:02:06【问题描述】:我有一系列div,其中id用常规标记:<divid="result<%=order.ID%>">提交表单的处理程序可以通过以下方式找出order.ID是... 查看详情
如何在运行时动态更改组件模板?角 4
】如何在运行时动态更改组件模板?角4【英文标题】:Howtodynamicchangecomponenttemplateatruntime?.Angular4【发布时间】:2017-12-0800:46:29【问题描述】:我有一个菜单栏和操作面板。操作面板只是简单的div,我想在其中显示不同的组件。... 查看详情
在材质 UI 中动态更改选项卡内容
】在材质UI中动态更改选项卡内容【英文标题】:ChangetabcontentdynamicallyinmaterialUI【发布时间】:2017-02-0500:58:03【问题描述】:我的反应应用程序页面中有一个包含选项卡(材料ui)的div。它有两个选项卡。其中一个选项卡具有列... 查看详情
使用 jquery 动态创建具有递增 id 的 div
...题描述】:我有一个文本我想附加多个div,但id应该动态更改。例如:<divid=first>text</div><divid=first0>text</div><divid 查看详情
AngularJS - 如何动态更改组件控制器?
】AngularJS-如何动态更改组件控制器?【英文标题】:AngularJS-Howtochangecomponentscontrollerdynamically?【发布时间】:2021-02-0212:03:19【问题描述】:我有一个angularJS组件,我手动设置了链接的url。但我想在blogposts以不同的方法加载后更改... 查看详情
如何为所有动态生成的 div 添加常用的 Javascript 函数? [复制]
】如何为所有动态生成的div添加常用的Javascript函数?[复制]【英文标题】:HowtoaddcommonJavaScriptfunctiontoalldivgenerateddynamically?[duplicate]【发布时间】:2015-07-1909:06:17【问题描述】:如何将javascript函数添加到动态生成的所有div中。在_d... 查看详情
在 ngFor 中动态分配元素 id
】在ngFor中动态分配元素id【英文标题】:DynamicallyassignelementidinsidengFor【发布时间】:2018-09-1009:32:24【问题描述】:我正在尝试为*ngFor中的div动态分配id。我希望将div称为“wave1、wave2、wave3”等。<li*ngFor="letepisodeofepisodes;leti=inde... 查看详情
vue滑动条组件封装
...保持覆盖在input标签上,4.通过input事件获取到input的改变,动态的改变div标签的宽,默认宽度是0.5.使用两个inputtype='range'元素的主要原因是为了实现点击彩色位置滑动条也能动提示:(组件是项目中用到,而且公司项目不可以用ui框... 查看详情
使用jquery ui拖放后的动态div宽度
】使用jqueryui拖放后的动态div宽度【英文标题】:Dynamicdivwidthafterdropusingjqueryui【发布时间】:2020-12-1506:44:37【问题描述】:我需要创建一个工作流构建器。我使用jqueryui进行拖放。我将元素拖到带有画布ID的div上。这是它的cssoverf... 查看详情
extjs为动态生成的组件绑定事件
...页面元素绑定事件,但是有些元素是在运行中,随着需要动态添加的,那这部分页面元素如何为他们绑定事件呢?举个例子,比如在jquery中,如果$("id").onclik()只能为原有页面元素绑定事件,对于动态加入的,可以写成$(&q... 查看详情
jquery动态创造div的并创建不同的id值
通过Jquery动态创建div,并给div的id付不同的值,并动态的获得div的id值,例如<divid="div1"></div><divid="div2"></div><divid="div3"></div><divid="div4"></div>// 你好,以在 BOD... 查看详情
在哪里释放动态分配的 TFrame 组件的对象?
】在哪里释放动态分配的TFrame组件的对象?【英文标题】:WheretofreedynamicallyallocatedTFrame\'scomponents\'objects?【发布时间】:2013-02-0904:47:03【问题描述】:我有一个包含TFrame的表单。TFrame包含一个动态填充的ComboBox。每个ComboBox条目... 查看详情
在js里动态生成div的问题
...quot;;div.style.backgroundColor="red";这段代码对吗为什么动态生成没有效果。如果不对能给一段正确的代码吗?参考技术A你没有把div显示出来啊。 参考技术Bdocument.body.appendChild(obj);创建了还是要在document里添上才行的 查看详情