Thursday 27 October 2016

How to clean the 'input' list from deleted Shiny input widgets

My Shiny application allows the user to create/delete inputs dynamically.



I then loop over these inputs to get the values (eg. val1 <- input[["input_for_val1"]]).



My problem is that values from deleted inputs remain in the shiny 'input' list.



I have tried removing the html widgets using removeUI or javascript (plus unbindAll/bindAll) but it does not help, I guess because once the value is in the 'input' list, it stays there until something on the UI updates it.



I also tried to edit the 'input' list itself (on the server side) but I get an error because it is readonly.




Any idea on how to clean the 'input' list from deleted shiny input widgets ?



Here is the code of a small project to illustrate the problem:



ui.R



library(shiny)

# Define UI for dataset viewer application
shinyUI(fluidPage(


# Javascript to handle the add/remove action of inputs
tags$head(tags$script(src="script.js")),

# Container where the script adds the dynamic inputs
tags$div(id = "container_for_dynamic_inputs"),

# 'Add' button
tags$button(onclick="addNewInputText()",
class = "btn btn-default",

"Add input"),

# 'Remove' button
tags$button(onclick="removeLastInputText()",
class = "btn btn-default",
"Remove input"),

# Keeps tracks of the number of inputs (see server.R)
verbatimTextOutput("summary")


)
)


www/script.js



var number_of_dynamic_inputs = 0;

var addNewInputText = function () {
console.log("addNewInputText");


var container_elt = document.getElementById("container_for_dynamic_inputs");

Shiny.unbindAll(container_elt);

var new_input = document.createElement("input");
var id = "input_" + number_of_dynamic_inputs++;
new_input.setAttribute("id", id);
new_input.setAttribute("name", id);
new_input.setAttribute("type", "text");

new_input.setAttribute("value", id);

container_elt.append(new_input);

Shiny.bindAll(container_elt);

}


var removeLastInputText = function () {


var container_elt = document.getElementById("container_for_dynamic_inputs");

Shiny.unbindAll(container_elt);

number_of_dynamic_inputs--;
var id = "input_" + number_of_dynamic_inputs ;

console.log("removeLastInputText: ", id);


var elementToRemove = document.getElementById(id);

container_elt.removeChild(elementToRemove);

Shiny.bindAll(container_elt);

}


server.R




library(shiny)

shinyServer(function(input, output) {

output$summary <- renderPrint({
for (i in names(input)) {
print(input[[i]])
}
})


})

No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...