如何在Shiny中计算来自textInput框的数据?

4
UI代码:
===
library(shiny)

  shinyUI(

    # Use a fluid Bootstrap layout
    fluidPage(    


      # Generate a row with a sidebar
      sidebarLayout(      


        # Define the sidebar with one input
        sidebarPanel(
          sliderInput("capacity", "Current Capacity:", 
                      min=0, max=100, value=10),
          c(list(
            textInput("service", "Service Component Name", ""),
            actionButton("addbtn", "Add Component"))),
            #lapply(seq(10), function(i) uiOutput(paste0("ui", i)))

            br(),
            br(), 
            br(),
            br(),
            br(),
          actionButton("calcbtn", "Calculate Projection")




        ),



        # Create a spot for the barplot
        mainPanel(
          textInput("inputWork","Volume", width="200px"),
          textInput("inputGrowth","Growth Rate", width="100px"),
          lapply(seq(10), function(i) uiOutput(paste0("ui", i)))
          #tags$p("Web"),
          #verbatimTextOutput("input_type_text")

        )

      )
    )
  )

服务器代码:

   server <- function(input, output) 
{
  observeEvent(input$addbtn, {
    n <- isolate(input$addbtn)
    if (n == 0) return()

    # create n-th pair of text input and output
    output[[paste0("ui", n)]] <- renderUI(
      list(textInput(paste0("textin", n), isolate(input$service)),
           textOutput(paste0("textout", n))))

    # display something in the output
    output[[paste0("textout", n)]] <- renderText({
      work<-as.numeric(input$inputWork)
      growth<-as.numeric(input$inputGrowth)
      print(growth)


     #paste("projection", (100+growth)*as.numeric(input[[paste0("textin", n)]]))
    })
  })
  observeEvent(input$calcbtn, {
    n <- isolate(input$calcbtn)
    if (n == 0) return()

    output[[paste0("textout", n)]] <- renderText({
      work<-as.numeric(input$inputWork)
      growth<-as.numeric(input$inputGrowth)
      project<-growth+as.numeric(input$service)

      print(growth)
      print(project)

      paste("projection", ((1+growth/100)*as.numeric(input[[paste0("textin", n)]])))
    })
  })
}

这是我想做的事情。代码将有一个初始文本框和提交按钮。用户在第一个输入文本中放入文本,单击提交按钮,在主面板中生成新文本。用户可以多次进行此操作,在主面板中创建多个文本输入框。
另外,我还有一个静态的名为“工作负载”的另一个inputText框位于主面板顶部。
所以,这就是我想做的:
1.用户将数据插入工作负载textIntut(它需要是数字)中。 2.用户将数据插入其他动态生成的textInput框中(所有内容都需要是数字)。 3.我将从工作负载和所有其他文本框中获取值,进行一些计算和投影,并在每个动态生成的textInput框旁边显示数据。如果我可以在生成的文本框旁边插入文本框来显示我的输出,那将是很棒的。
例如,我在我的工作负载中有数据,我已经生成了Web_server、App_server textInput框。我将从工作负载中获取数据,并将其除以web_server中的数据,然后在web_server textInput框旁边显示它(在文本框中显示数据),对app_server textInput框执行相同的操作。
你有任何想法如何在shiny中实现这个功能吗?这是我试图完成的图片。给定从用户那里获取的工作负载增长率和用户输入部分的其他输入,我必须计算并填写相应的文本框。

1
假设 calcbtn 在 UI 中已经定义,当你点击它时,预期的行为是什么?这会更新所有动态创建的 textOutput 吗,还是只更新其中一个? - Kota Mori
1
这种行为是你的代码所期望的。它逐一更新“textOutput”。此外,从代码中我猜测,即使你更改了“textInput”并再次单击“calcbtn”,“textOutput”也不会再次更新。现在,当单击“calcbtn”时,你期望的行为是什么? - Kota Mori
1
当提出问题时,您不应单独复制和粘贴ui.Rserver.R。这样会让人们需要创建一个文件夹,并创建两个文件来尝试您的代码。相反,准备一组代码,人们可以简单地将其复制到他或她的编辑器中并运行它。 - Kota Mori
1
很遗憾,不行。看起来你在收到答案后更新了你的问题。你不应该这样做,因为如果你改变了问题,这个线程对于后来看到它的其他人就变得毫无意义了。如果你的原始问题已经解决了,只需接受并在必要时开一个新的线程即可。 - Kota Mori
1
此外,在提问时,请尽量提供一个最小可重现的示例。你当前的问题听起来像是在要求别人帮你找出代码中的错误。相反,只需描述你想要做什么以及你遇到了什么困难,这样别人才能更好地帮助你。 - Kota Mori
显示剩余15条评论
2个回答

2
下面的代码实现:
  1. 点击按钮时添加文本输入(和输出)(最多10个)。
  2. 每个文本输出都使用输入信息显示一些消息。

注意:

  • 文本输出出现在下方,而不是旁边。这更多是设计问题。我不是很熟悉HTML或CSS,抱歉。
  • 这完全没有计算。你的任务是添加更多组件并根据需要更改renderText的内容。
  • 我使用textOutput来显示计算结果,但您可能想使用textInput。通常,应使用textOutput显示某些内容,尽管也可以将输入对象用作输出。
  • 我使用了textInput,但如果输入应始终为数字,则可以使用numericInput,如其中一个注释所示。

玩得开心。

library(shiny)

ui <- c(list(
  textInput("service", "Service Component Name", ""),
  actionButton("addbtn", "add")),
  lapply(seq(10), function(i) uiOutput(paste0("ui", i)))
)


server <- function(input, output) 
{
  observeEvent(input$addbtn, {
    n <- input$addbtn
    if (n == 0) return()
    if (n > 10) return()

    # create n-th pair of text input and output
    output[[paste0("ui", n)]] <- renderUI(
      list(textInput(paste0("textin", n), isolate(input$service)),
           textOutput(paste0("textout", n))))

    # display something in the output
    output[[paste0("textout", n)]] <- renderText({
      paste("you wrote", input[[paste0("textin", n)]])
    })
  })
}

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

抱歉,我忘记提到了。输出需要通过一个命令按钮生成。一旦所有输入都准备就绪,用户需要能够按下提交按钮,然后输出框将填充数据。您能修改这个功能吗?感谢您的帮助! - user1471980
还有一个按钮可以清除所有字段而不刷新页面吗? - user1471980
这里有一种清除所有字段的方法:https://dev59.com/62Af5IYBdhLWcg3wylMd - Zediiiii
你也可以做到。添加一个按钮并重写renderText部分。这是你的任务!提示:使用isolateobserveEvent - Kota Mori
@user1471980,你可以使用shinyjs包中的reset()函数来清除输入。 - DeanAttali
显示剩余2条评论

1
实现您的愿望的几个提示如下:
  • renderText 检查其组件的更改,并在组件的值被修改时执行。这就是为什么使用 input$textin1 时,在文本输入框中输入后会立即更新的原因。
  • isolate 防止组件触发执行。使用 isolate(input$textin1),修改文本输入框中的内容不会更新 textOutput
  • 要使按钮触发 renderText 的执行,只需将按钮添加到 renderText 中即可。内部实现时,当单击按钮时,其值会增加。因此,函数检查了一个组件的值修订,执行发生。
  • 最后,您需要对所有的 textin1textin2 等进行此操作。

以下代码实现了这一点。与以前的答案相比较一下。

library(shiny)

ui <- c(list(
  textInput("service", "Service Component Name", ""),
  actionButton("addbtn", "add"), 
  actionButton("calcbtn", "calc")),
  lapply(seq(10), function(i) uiOutput(paste0("ui", i)))
)


server <- function(input, output) 
{
  observeEvent(input$addbtn, {
    n <- input$addbtn
    if (n == 0) return()
    if (n > 10) return()

    # create n-th pair of text input and output
    output[[paste0("ui", n)]] <- renderUI(
      list(textInput(paste0("textin", n), isolate(input$service)),
           textOutput(paste0("textout", n))))

    # display something in the output
    output[[paste0("textout", n)]] <- renderText({
      input$calcbtn
      paste("you wrote", isolate(input[[paste0("textin", n)]]))
    })
  })
}

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接