分配/更改动态生成的 UI 组件的 div ID (R Shiny/Javascript)

     2023-03-24     124

关键词:

【中文标题】分配/更改动态生成的 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)

【问题讨论】:

你为什么不使用更闪亮的方式,使用rHandsontableOutputrenderRHandsontable 代替? renderUI 更静态。 我不知道如何使用 rHandsontableOutput 创建未知数量的表。以这种方式生成的每个表都不需要一个 output$ 占位符吗?我事先不知道我需要创建多少对象,因此我求助于 renderUI。如果你能分享一个 sn-p 会很有帮助 在 R 中访问list 的另一种方式是list[['item_name']],所以你可以使用output[['xx']] &lt;- xxx。换上lapply(tables, function(x)output[[x]] &lt;- 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里添上才行的 查看详情