R有光泽:动态创建不同类型的表格输入

时间:2015-11-14 18:16:34

标签: r dynamic input shiny tabular

我已经搜索了很长一段时间,但我还没有找到解决问题的办法。我正在构建一个项目管理应用程序,我想使用闪亮,因为我认为它将能够使应用程序更具互动性。

因此应用程序的输入应该在应用程序内完成。输入将是数字,文本和选项。总而言之,属于一起的输入应排列在一行中。例如:

resource_1,name ='共聚焦显微镜',键入=' machine',price = 1000,price_type =' EUR / usage'

我想以表格形式安排每个条目。当然,条目的数量是可变的。有时您可能为项目定义5个资源,有时为50个。

为解决这个问题,我使用html元素作为表条目创建了一个闪亮的表格。但是,我需要动态访问这些条目。我想我可以通过使用get()函数调用每个表项的输入ID的字符串来实现。但这不起作用。

现在:

  • 我可以创建一个包含不同类型输入和可变行数的表格。

  • 我可以通过实际调用输入ID来调用每个输入(例如输入$ element1_1'

  • 但我无法循环自动访问这些输入ID,例如get():get(paste0(' input $ element',i, ' _',j)的)

最小例子:

library(shiny)

ui = 
  pageWithSidebar(

headerPanel("TEST"),

sidebarPanel(
  helpText("number of resources"),
  numericInput("nres","",3,min=0),
  actionButton('create_res',"create",icon=icon("plus"),width='100%'),
  br(),
  br(),
  br(),
  bsButton('finish_res',"finish",width='100%',style="info"), # check matrix
  width=2
),

mainPanel(    
  uiOutput('matrix_res'),
  p("make an entry in row1 col1 and press finish"),
  br(),
  p("I can extract elements by calling input$element1_1:"),
  textOutput('check1'),
  br(),
  p("but not by searching for the character string with get('element1_1') "),
  textOutput('check2')
)
)

server = 
  function(input,output){

output$matrix_res <- renderTable({

  input$create_res #create button dependency


  Row_entries <- paste("ressource",1:isolate(input$nres)) #kill nres dependency
  Col_entries <- c("text input","number input","selection")

  matrix <- data.frame()

  for (i in 1:length(Row_entries)) {
    matrix[i,1] <- paste0("<input id='element", i, "_", 1, "' class='shiny-bound-input span6' type='text' value=''>") 
    matrix[i,2] <- paste0("<input id='element", i, "_", 2, "' class='shiny-bound-input span6' type='number' value=''>")
    matrix[i,3] <- paste0("<div class='form-group shiny-input-container'>
                          <div>
                          <select id='element", i, "_", 3, "' class='form-control'><option value='a' selected>a</option>
                          <option value='b'>b</option></select>
                          <script type='application/json' data-for='element", i, "_", 3, "'>{}</script>
                          </div></div>") 
  }

  colnames(matrix) <- Col_entries

  matrix

  },sanitize.text.function = identity)


output$check1<-renderText({
  input$finish_res
  isolate(input$element1_1)
})

output$check2<-renderText({
  input$finish_res
  isolate(input$get('element1_1'))
})
}

runApp(list(ui = ui, server = server))

运行它:您可以使用数字输入和创建按钮更改行数。您可以通过单击“完成”来调用row1 column1的值。

如果您有任何想法如何掌握这些输入,请回复。我已经坚持这个狗屎一周了......

2 个答案:

答案 0 :(得分:0)

所以我找到了一个令人不满意的答案。 我尝试使用get(),eval(),do.call()以及以下实际工作:

的eval(解析(文本= character_string))

所以你可以使character_string&lt; - paste0(&#39;输入$ element&#39;,i,&#39; _&#39;,j)或其他东西

因此,通过这个,你可以循环遍历所有输入并为所有输入创建一个列表。实际上,我希望可以直接将所有输入保存到列表中。

所以这是一个例子:

library(shiny)

ui = 
pageWithSidebar(

headerPanel("TEST"),

sidebarPanel(
  helpText("number of rows"),
  numericInput("nres","",3,min=0),
  actionButton('create_res',"create",icon=icon("plus"),width='100%'),
  br(),
  br(),
  br(),
  helpText("show me value in row 1 column 1"),
  actionButton('finish_res',"show",icon=icon("check"),width='100%'),
  width=2
),

mainPanel(    
  uiOutput('matrix_res'),
  p("just by actually writing 'input$element1_1'"),
  textOutput('check1'),
  br(),
  p("with get(character_string)"),
  textOutput('check2'),
  br(),
  p('with eval(parse(text=character_string)):'),
  textOutput('check3'),
  br(),
  p('with do.call("print", list(as.name(character_string)))'),
  textOutput('check4')
)
)

server = 
function(input,output){

output$matrix_res <- renderTable({

  input$create_res #create button dependency


  Row_entries <- paste("ressource",1:isolate(input$nres)) #kill nres dependency
  Col_entries <- c("text input","number input","selection")

  matrix <- data.frame()

  for (i in 1:length(Row_entries)) {
    matrix[i,1] <- paste0("<input id='element", i, "_", 1, "' class='shiny-bound-input span6' type='text' value=''>") 
    matrix[i,2] <- paste0("<input id='element", i, "_", 2, "' class='shiny-bound-input span6' type='number' value=''>")
    matrix[i,3] <- paste0("<div class='form-group shiny-input-container'>
                          <div>
                          <select id='element", i, "_", 3, "' class='form-control'><option value='a' selected>a</option>
                          <option value='b'>b</option></select>
                          <script type='application/json' data-for='element", i, "_", 3, "'>{}</script>
                          </div></div>") 
  }

  colnames(matrix) <- Col_entries

  matrix

  },sanitize.text.function = identity)


output$check1<-renderText({
  input$finish_res
  isolate(input$element1_1)
})

output$check2<-renderText({
  input$finish_res
  isolate(get(paste0('input$element',1,'_',1)))
})

output$check3<-renderText({
  input$finish_res
  isolate(eval(parse(text=paste0('input$element',1,'_',1))))
})

output$check4<-renderText({
  input$finish_res
  isolate(do.call("print",   list(as.name(paste0('input$element',1,'_',1)))))
})

 }

runApp(list(ui = ui, server = server))  

答案 1 :(得分:0)

好的,这是获得我想要的方式。

我确信有更好的方法可以做到这一点,因为这对于像这样的简单任务来说太复杂了。

请注意,如果您决定添加更多行,则会保存输入。

warning: sizeof on array function parameter will return size of 'entry *' instead of 'entry []' [-Wsizeof-array-argument]