当x = 0时执行Math.pow(10,x)时,使用JavaScript更改R Shiny错误中的noUIslider标签 [英] Using javascript to alter noUIslider tags in R Shiny error when performing Math.pow(10,x) when x = 0
问题描述
In an earlier SO question here I have come to a point where I have a noUiSliderInput
that gets it's labels updated to a scientific notation format with the help of javascript
.
剩下的问题是,当输入为0时noUiSliderInput
会跳到10,因此它应该跳到1.(10 ^ 0是1,而不是10).我怀疑是Math.pow(10,x)的问题,但我不确定
The remaining problem is that the noUiSliderInput
jumps to 10 when the input is 0 and it therefore should jump to 1. (10^0 is 1, not 10). I suspect a problem with Math.pow(10,x) is the cause but I am not sure
更新:
通过更改javascript
代码已解决了滑块跳转到最大值的最初问题,该代码现在将shiny
中的值用作滑块的min,max和value的输入.
我已在问题中更改了应用程序的代码以表示当前情况.
UPDATE:
The initial problem of the slider jumping to the maximum value has been fixed by changing the javascript
code, which now takes values from shiny
as input for the min, max and value of the slider.
I have changed the code of the app here in the question to represent the current situation.
#END UPDATE#
这里的行为是通过使用第二个sliderInput
和numericInput
框模拟的,该框会导致noUiSliderInput所需的所有三个值都改变
The behavior is simulated here with the use of a second sliderInput
and numericInput
boxes that causes all three values needed for the noUiSliderInput to cahange
在我的实际app
中,noUiSliderInput
链接到plot
,并且用户选择的任何数据column
都链接到plot
.因此,用户选择绘制的任何数据将需要noUiSliderInput
至update
,即range
. slider
也链接到具有较早创建的设置的datatable
(数据中某些列的阈值的数据表),并且当用户单击datatable
条目时,它会update
向下选择将要绘制的数据(以及noUiSliderInput
range
)以及阈值(noUiSliderInput
value
)应基于datatable
中的值的高度.
In my real app
the noUiSliderInput
is linked to a plot
, and whatever data column
the user chooses to plot
. So, whatever data the user chooses to plot will require the noUiSliderInput
to update
it's range
. The slider
is also linked to a datatable
with earlier created settings (a datatable of threshold values for some of the columns in the data), and when the user clicks a datatable
entry, it will update
the drop down that selects which data is to be plotted (and thus the noUiSliderInput
range
), as well as at what height the threshold (noUiSliderInput
value
) should be based on the value in the datatable
.
这一次触发三个变化,即范围(即noUiSliderInput
的最小值和最大值)以及noUiSliderInput
的值.
This fires three changes at once, range (i.e. min & max of noUiSliderInput
), as well as value of the noUiSliderInput
.
我设法得到了一个模拟该行为的虚拟app
,除了noUiSliderInput
的value
被当前的javascript
似乎错误地更新了.
I managed to get a dummy app
that simulates this behavior working, except the value
of the noUiSliderInput
gets updated wrong by the current javascript
it seems.
示意图大致如下所示
The schematic looks like this roughly
在这里您可以看到单击table
会将值发送到noUiSliderInput
值,并将参数名称发送给参数selectInput
,然后获取数据并将其发送到plot
,并将最小值,最大值:range
发送到noUiSliderInput
.
之所以这样构建,是因为用户还可以直接从selectInput
中选择参数(columns
)(其中许多不在阈值表中)
Where you can see that clicking on the table
will send a value to the noUiSliderInput
value, and a parameter name to the parameter selectInput
, which then gets the data, sends it to the plot
, and send the min, max: range
to the noUiSliderInput
.
It is build this way because the user can also select parameters (columns
) from the selectInput
directly (many of which are not in the table of thresholds)
到目前为止的应用程序:
library(shiny)
library(shinyWidgets)
library(shinyjs)
js <- function(Min, Max, Start){
sprintf(paste(
"var slider = document.getElementById('Histoslider').noUiSlider;",
"slider.updateOptions({",
" start: %s,",
" range: {min: %s, max: %s},",
" format: wNumb({",
" encoder: function(x){return parseFloat(Math.pow(10,x));}",
" })",
"});",
"var pipsValues = $('.noUi-value');",
"pipsValues.each(function(){$(this).html('10<sup>'+$(this).attr('data-value')+'</sup>')});",
sep = "\n"
), Start, Min, Max)
}
ui <- fluidPage(
useShinyjs(),
tags$br(),
fluidRow(
column(4,
uiOutput('TestSliderOut'),
actionButton(inputId = "UpdateSlider", label = 'Update')
),
column(6,
sliderInput("slider2", label = NULL, min = -5, max = 20, value= c(1, 5), step = 1),
numericInput(inputId = 'SlMin', label = 'Min', value = 1, min = -5, max = 20),
numericInput(inputId = 'SlMax', label = 'Max', value = 5, min = -5, max = 20),
numericInput(inputId = 'SlVal', label = 'Val', value = 3, min = -5, max = 20),
br(),
h5('Update counter'),
verbatimTextOutput(outputId = "updates"),
h5('slider value'),
verbatimTextOutput(outputId = 'ouputval')
)
)
)
server <- function(input, output, session) {
values <- reactiveValues( Counter = 0)
output$TestSliderOut <- renderUI({
noUiSliderInput(
inputId = "Histoslider", label = "Slider vertical:",
min = -2, max = 4, step = 0.01,
value = 0, margin = 100,
pips = list(mode="range", density=2),
orientation = "vertical",
width = "300px", height = "300px", direction = "rtl",
behaviour = "tap"
)
})
observeEvent(input$slider2, {
## simulates the change of multipe parameters of the slider: min, max, value
newvalue <- (input$slider2[2]-input$slider2[1])/2+input$slider2[1]
updateNumericInput(session, inputId = 'SlMin', value = input$slider2[1])
updateNumericInput(session, inputId = 'SlMax', value = input$slider2[2])
updateNumericInput(session, inputId = 'SlVal', value = newvalue)
})
observe({
updateNoUiSliderInput(session, inputId = 'Histoslider', range = c(input$SlMin, input$SlMax), value = input$SlVal)
shinyjs::delay(1, { ## delay the javascript so that it runs after the slider has updated its values
runjs(js(input$SlMin, input$SlMax, input$SlVal)) })
})
output$updates <- renderPrint(values$Counter)
output$ouputval <- renderPrint(input$Histoslider)
observeEvent(input$SlMin, { values$nouiMin <- input$SlMin })
observeEvent(input$SlMax, { values$nouiMax <- input$SlMax })
observeEvent(input$SlVal, { values$nouiVal <- input$SlVal })
observeEvent(input$Histoslider, {
print('changing code')
runjs(js(values$nouiMin, values$nouiMax, values$nouiVal)) ## fires ones on first build of the slider
}, once = TRUE)
}
shinyApp(ui, server)
推荐答案
嗯,看起来确实很奇怪.似乎可以通过使用set
方法(设置滑块的值)而不是更新start
选项来工作:
Hmm that does look strange. It seems to work by using the set
method (set the value of the slider) instead of updating the start
option:
js <- function(Min, Max, Start){
sprintf(paste(
"var slider = document.getElementById('Histoslider').noUiSlider;",
"slider.updateOptions({",
" range: {min: %s, max: %s},",
" format: wNumb({",
" decimals: 2,",
" encoder: function(x){return parseFloat(Math.pow(10,x));}",
" })",
"});",
"slider.set(%s);",
"var pipsValues = $('.noUi-value');",
"pipsValues.each(function(){$(this).html('10<sup>'+$(this).attr('data-value')+'</sup>')});",
sep = "\n"
), Min, Max, Start)
}
请注意,代码中的updateNoUiSliderInput
是无用的,因为滑块是由JS代码更新的.因此,替换
Note that the updateNoUiSliderInput
in your code is useless, because the slider is updated by the JS code. So replace
observe({
updateNoUiSliderInput(session, inputId = 'Histoslider', range = c(input$SlMin, input$SlMax), value = input$SlVal)
shinyjs::delay(1, { ## delay the javascript so that it runs after the slider has updated its values
runjs(js(input$SlMin, input$SlMax, input$SlVal)) })
})
使用
observeEvent(list(input$SlMin, input$SlMax, input$SlVal), {
runjs(js(input$SlMin, input$SlMax, input$SlVal))
}, ignoreInit = TRUE)
这篇关于当x = 0时执行Math.pow(10,x)时,使用JavaScript更改R Shiny错误中的noUIslider标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!