I have a custom shiny input which is a balanced set of sliders. I am trying to use the updateBalancedSliderInput so I can reset the values to their defaults. However, in my app, this updateBalancedSlider function does not kick off any reactives in order to update the outputs. Javascript and shiny example below. My assumption is I just need something in my js file to kick off the reactives on the server side. The UI updates just fine when trying to update the balanced slider, just not any outputs depending on changes in those values. Any help is much appreciated.
Shiny
### Shiny Inputs
library(shiny)
balancedSliderInput <- function(inputId, value = 0, label = "",
group = "", width = "100%") {
if (label != "")
label <- paste0('<label class="control-label" for="', inputId, '">', label, '</label>')
balanced_slider_tag <- tagList(
div(style = paste("width: ", width), class = "all-balanced-slider",
HTML(label),
div(id = inputId, class = paste("balanced-slider", group), as.character(value)),
span(class = "value", "0"),
HTML("%")
)
)
dep <- list(
htmltools::htmlDependency("balanced_slider", "0.0.2", c(file = "www"),
script = c("js/jquery-ui.min.js", "js/balancedSlider.js"),
stylesheet = c("css/jquery-ui.min.css")
)
)
htmltools::attachDependencies(balanced_slider_tag, dep)
}
updateBalancedSliderInput <- function(session, inputId, value = 0) {
message <- list(value = value)
session$sendInputMessage(inputId, message)
}
registerInputHandler("balancedSlider", function(data, ...) {
if (is.null(data))
NULL
else
data
}, force = TRUE)
########## App ------
ui <- fixedPage(
actionButton("reset", "Reset", icon = icon("undo-alt")),
balancedSliderInput("test1", label = "Test1", value = 50),
balancedSliderInput("test2", label = "Test2", value = 50),
textOutput("test")
)
server <- function(session, input, output) {
test_reactive <- reactive({
return(input$test1)
})
output$test <- renderText({
test <- paste("Sluder 1 is at", test_reactive()[[1]])
return(test)
})
observeEvent(input$reset, {
updateBalancedSliderInput(session, "test1", 50)
updateBalancedSliderInput(session, "test2", 50)
})
}
shinyApp(ui, server)
Javascript
$(function() {
$('.balanced-slider').each(function() {
console.log("Running Log 1")
var init_value = parseInt($(this).text());
$(this).siblings('.value').text(init_value);
$(this).empty().slider({
value: init_value,
min: 0,
max: 100,
range: "max",
step: 0.5,
animate: 0,
slide: function(event, ui) {
console.log("Log 10");
// Update display to current value
$(this).siblings('.value').text(ui.value);
// Get current total
var total = ui.value;
var sibling_count = 0;
var classes = $(this).attr("class").split(/\s+/);
var selector = ' .' + classes.join('.');
//console.log(selector);
var others = $(selector).not(this);
others.each(function() {
total += $(this).slider("option", "value");
sibling_count += 1;
});
//console.log(total);
var delta = total - 100;
var remainder = 0;
// Update each slider
others.each(function() {
console.log("Running Log 2")
var t = $(this);
var current_value = t.slider("option", "value");
var new_value = current_value - delta / sibling_count;
if (new_value < 0) {
remainder += new_value;
new_value = 0;
}
t.siblings('.value').text(new_value.toFixed(1));
t.slider('value', new_value);
});
if(remainder) {
var pos_val_count = 0;
others.each(function() {
if($(this).slider("option", "value") > 0)
pos_val_count += 1;
});
others.each(function() {
if($(this).slider("option", "value") > 0) {
var t = $(this);
var current_value = t.slider("option", "value");
var new_value = current_value + remainder / pos_val_count;
t.siblings('.value').text(new_value.toFixed(1));
t.slider('value', new_value);
}
});
}
},
// fire the callback event for the other sliders
stop: function(event, ui) {
var classes = $(this).attr("class").split(/\s+/);
var selector = '.' + classes.join('.');
$(selector).not(this).each(function() {
$(this).trigger("slidestop");
});
}
});
});
});
var balancedSliderBinding = new Shiny.InputBinding();
$.extend(balancedSliderBinding, {
find: function(scope) {
return $(scope).find(".balanced-slider");
},
// The input rate limiting policy
getRatePolicy: function() {
return {
// Can be 'debounce' or 'throttle'
policy: 'debounce',
delay: 500
};
},
getType: function() {
return "balancedSlider";
},
getValue: function(el) {
var obj = {};
obj[$(el).attr("id")] = $(el).slider("option", "value");
return obj;
},
setValue: function(el, new_value) {
$(el).slider('value', new_value);
$(el).siblings('.value').text(new_value);
},
subscribe: function(el, callback) {
$(el).on("slidestop.balancedSliderBinding", function(e) {
callback(); // add true parameter to enable rate policy
});
},
unsubscribe: function(el) {
$(el).off(".balancedSliderBinding");
},
// Receive messages from the server.
// Messages sent by updateUrlInput() are received by this function.
receiveMessage: function(el, data) {
if (data.hasOwnProperty('value'))
this.setValue(el, data.value);
$(el).trigger('change');
},
});
Shiny.inputBindings.register(balancedSliderBinding, "balancedSliderBinding");
If you replace the following line in receiveMessage
:
$(el).trigger('change');
with
$(el).trigger('slidestop');
it works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With