【问题标题】:Replace existing R shiny htmlwidget data with new data用新数据替换现有的 R 闪亮 htmlwidget 数据
【发布时间】:2017-11-05 01:08:39
【问题描述】:

我已经为我的 R 闪亮应用程序创建了一个 htmlwidget。在我的小部件中,我无法用新数据替换现有数据,每当多次调用小部件渲染函数时,这都会导致错误,并且旧数据未被删除,新数据将附加旧数据。

我创建了一个可重现的示例来显示我的问题。当您单击“ui2”按钮时,应用程序会转到另一个 ui,当您单击“reset”按钮时,应用程序会从该 ui 中返回默认 ui,您可以看到在同一个中会有两个直方图容器而不是一个。这是因为我无法用 htmlwidget 中的新数据替换旧数据。

可重现的闪亮应用:

#library(devtools)
#install_github('radhikesh/d3Viz')
library(shiny)
library(d3Viz)
ui <- shinyUI(fluidPage(

fluidRow(
column(12,uiOutput("page"))) 
))

ui1 <- function() {
fluidPage(

fluidRow( column(11, 
               div(
                 id = "ResetBtn5", actionButton("ui2", "ui2", style="color: 
#fff; background-color: #337ab7; border-color: #2e6da4")
               ))),

br(),

fluidRow(
column(width = 6, d3HistogramOutput("d3Hist"))
),

br(),
br(),
br(),
br(),
br(),
br(),

fluidRow(
column(12, DT::dataTableOutput("DataAric"))
)

)}

ui2 <- function() {
fluidPage(

fluidRow( column(11, 
                 div(
                   id = "ResetBtn5", actionButton("ResetButtonAric", 
"Reset", style="color: #fff; background-color: #337ab7; border-color: 
#2e6da4")
                 ))),

br(),


fluidRow(
  column(width = 6, d3HistogramOutput("d3Hist2"))
)


)}


server <- shinyServer(function(input, output) {

dataset <- data.frame(lpu = c('Apple','Banana','Apple'), amount = 
                      c(20,10,10))

output$page <- renderUI({
div(class = "outer", do.call(bootstrapPage, c("", ui1())))
})



output$d3Hist <- renderD3Histogram({ 
k <- input$DataAric_rows_all
if (length(k) > 0)
{

  trialAnnotate <- data.frame(table(dataset[k, "lpu"]))
  dataset = data.frame(lpu = trialAnnotate$Var1,amount = trialAnnotate$Freq)
  d3Histogram(dataset = dataset)

 }
})

output$DataAric <-
DT::renderDataTable(
dataset,
  options = list(
    pageLength = nrow( dataset),
    bLengthChange=F
  ),
  rownames = FALSE,
  escape = FALSE
)

output$d3Hist2 <- renderD3Histogram({ 

dataset <- data.frame(lpu = c('Apple','Banana','Orange'), amount = 
                        c(30,20,25))
d3Histogram(dataset = dataset)

})

observeEvent(input$ui2, {


output$page <- renderUI({
  div(class = "outer", do.call(bootstrapPage, c("", ui2())))
})


})

observeEvent(input$ResetButtonAric, {


output$page <- renderUI({
  div(class = "outer", do.call(bootstrapPage, c("", ui1())))
})


})

})

# Run the application 
shinyApp(ui = ui, server = server)

d3Histogram.js 代码

HTMLWidgets.widget({
  
  name: 'd3Histogram',
  
  type: 'output',
  
  renderOnNullValue: true,
  
  factory: function(el, width, height) {
    
    return {
      
      renderValue: function(x) {
        
        var container = d3.select(el).append("div").attr("id", "container");
        
        var barPadding = 1;
        
        /*
          var data=[
            {"lpu":"lpu1","amount":"20"},
            {"lpu":"lpu2","amount":"40"},
            {"lpu":"lpu3","amount":"60"},
            {"lpu":"lpu4","amount":"10"},
            {"lpu":"lpu5","amount":"80"},
            {"lpu":"lpu6","amount":"30"},
            {"lpu":"lpu7","amount":"20"},
            {"lpu":"lpu8","amount":"40"},
            {"lpu":"lpu9","amount":"60"},
            {"lpu":"lpu10","amount":"10"},
            {"lpu":"lpu11","amount":"80"},
            {"lpu":"lpu12","amount":"30"},
            {"lpu":"lpu13","amount":"20"},
            {"lpu":"lpu14","amount":"40"},
            {"lpu":"lpu15","amount":"60"},
            {"lpu":"lpu16","amount":"10"},
            {"lpu":"lpu17","amount":"80"},
            {"lpu":"lpu18","amount":"30"}
            ];
          */
            
            var dataset = HTMLWidgets.dataframeToD3(x.dataset);
            
            var width=2000,
            height=300;
            //radius=100,
            //	padding=100;
            
            var margin = {top: 100, right: 50, bottom: 40, left: 50};
            
            var xLPU=d3.scale.ordinal();
            var yLPU=d3.scale.linear();
            
            var xLPUAxis = d3.svg.axis()
            .scale(xLPU)
            .orient("bottom");
            
            var yLPUAxis = d3.svg.axis()
            .scale(yLPU)
            .orient("left")
            .ticks(20, "??????.");
            
            
            var svg1 = d3.select("#container").append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
            
            xLPU.domain(dataset.map(function(d){return d.lpu;}))
            .rangeBands([0, width]);
            yLPU.domain([0,d3.max(dataset, function(d) { return d.amount; })])
            .range([height,0]);
            svg1.append("g")
            .attr("class","x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xLPUAxis);      
            
            svg1.append('g')
            .attr('class','y axis')
            .call(yLPUAxis);
            
            
            svg1.selectAll('rect').data(dataset).enter().append('rect')
            .attr('x', function(d) {
              return xLPU(d.lpu);
            })
            .attr('y',function(d) {
              return yLPU(d.amount);
            })
            .attr('width',xLPU.rangeBand()-3)
            .attr('height', function(d) {
              return height - yLPU(d.amount);
            })
            .attr('fill','teal');
            // .attr("fill", function(d) {
              // return "rgb(0, 0, " + (d * 10) + ")";
              //  });
            
            svg1.selectAll(".bartext")
            .data(dataset)
            .enter()
            .append("text")
            .attr("class", "bartext")
            .attr("text-anchor", "middle")
            .attr("fill", "black")
            .attr("x", function(d,i) {
              return xLPU(d.lpu)+xLPU.rangeBand()/2;
            })
            .attr("y", function(d,i) {
              return yLPU(d.amount) + (-3);
            })
            .text(function(d){
              return d.amount   
            });
            
            svg1.selectAll('.axis line, .axis path')
            .style({'stroke': 'Black', 'fill': 'none', 'stroke-width': '2px'});
            
            svg1.append("text")      // text label for the x axis
            //.attr("x", 265 )
            //.attr("y", 240 )
            //.style("text-anchor", "middle")
            .attr("transform", "translate(" + (width / 2) + " ," + (height + margin.bottom) + ")")
            .text("Year")
            .attr('font-family','sans-serif')
            .attr('font-size','15px')
            .attr('fill','black');
            
            
            svg1.append("text")
            .attr("transform", "rotate(-90)")
            .attr("y", 0 - margin.left)
            .attr("x",0 - (height / 2))
            .attr("dy", "1em")
            .style("text-anchor", "middle")
            .text("Count")
            .attr('font-family','sans-serif')
            .attr('font-size','15px')
            .attr('fill','black');
            
            
            
      },
      
      resize: function(width, height) {
        
        
      }
      
    };
  }
});

我想,我知道问题所在,我必须在我的 java-script 绑定中用新数据替换旧数据,但我是 java-script 的新手,无法弄清楚。任何帮助将不胜感激。

谢谢

拉迪凯什

【问题讨论】:

    标签: javascript r shiny htmlwidgets


    【解决方案1】:

    我不确定这是否是最有效的答案,但我遇到了同样的问题,并通过在创建新子节点之前删除容器的子节点来解决它。

    尝试在 renderValue 函数的开头使用以下 while 循环

    while (document.getElementById(el.id).hasChildNodes()) {
        document.getElementById(el.id).removeChild(document.getElementById(el.id).lastChild);
    }
    

    【讨论】:

      【解决方案2】:

      您的“htmlwidget”会定期向浏览器发送消息,包括数据。这意味着它将新数据绑定到 DOM 并且 javascript 将再次运行。虽然数据用于绘制 SVG,但它仍然独立于 SVG 存在。问题不在于新数据(R 负责),而在于旧 SVG 维护其状态。

      在您的代码中,您无法删除 JS 文件中现有的 plot/svg(即使发送了新数据)。我通常使用类似的东西:

      this.element.innerHTML = '';

      其中this 是小部件的当前范围。 element 是小部件中的 el。设置 innerHTML = ''; 会清除 DOM 元素并允许您的脚本附加新图像。

      小部件的工作流程应在任何进一步绘图之前包括此类清洁。更复杂的小部件可以transition() 在 d3 中从以前的状态到新状态,但可能需要自定义绑定。

      【讨论】:

        猜你喜欢
        • 2016-06-09
        • 2021-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-17
        • 2018-09-26
        • 2014-05-06
        相关资源
        最近更新 更多