Is it possible to save and restore selections of a shinyTree?
I found a solution deleting the selections
R Shiny - Updating shinyTree node selections
but I need to save the selections and restore them later for example, by an actionButton
This is not possible with shinyTree only. Some functions of the underlying jsTree library have to be called directly and the values passed from JavaScript to R and vice-versa.
I made a small example, which should help you as a starting point.
If you save a selection via button-click, R sends a custom message to JavaScript, which will get the selected IDs and returns it to R via Shiny.setInputValue.
The selected ID's are then saved in the reactiveValues selectionRV, but you could save them in a file or database if needed.
library(shiny)
library(shinyTree)
library(shinyjs)
js <- HTML("
$(document).on('shiny:connected', function(event) {
Shiny.addCustomMessageHandler('saveselection', function(e) {
var selection = $('#tree').jstree().get_selected();
Shiny.setInputValue('treeselection', selection, {priority: 'event'});
});
})
")
## ui ####################
ui <- fluidPage(
useShinyjs(),
tags$head(tags$script(js)),
actionButton("deselect", "Deselect all"),
actionButton("savesele", "Save Selection"),
actionButton("restoresele", "Restore Selection"),
shinyTree("tree", dragAndDrop = TRUE,types= #Types is in the same format that jstree expects
"{
'#': { 'max_children' : 2, 'max_depth' : 4, 'valid_children' : ['root'] },
'root' : { 'valid_children' : ['file'] },
'default' : { 'valid_children' : ['default','file'] },
'file' : { 'icon' : 'fa fa-file', 'valid_children' : [] }
}"
)
)
## server ####################
server <- function(input, output, session) {
treeData <- reactive({
rootstrc <- structure(list(
SubListA = structure(list(
leaf1 = structure("",sttype="file",sticon="fa fa-signal"),
leaf2 = structure("",sttype="file",sticon="fa fa-signal"),
leaf3 = structure("",sttype="file",sticon="fa fa-signal")),
sttype="root",stopened=F,sticon="fa fa-signal"
),
SubListB = structure(list(
leafA = structure("",sttype="default",sticon="glyphicon glyphicon-leaf"),
leafB = structure("",sttype="default",sticon="shinyTree/icon.png"),
leafC = structure("",sttype="default",sticon="fa fa-signal")
),stopened=F,sttype="root",sticon="fa fa-signal")
),
sttype="root",stopened=F,sticon="fa fa-signal"
)
list(
root1 = rootstrc,
root2 = rootstrc,
root3 = rootstrc,
root4 = rootstrc
)
})
output$tree <- renderTree({
treeData()
})
selectionRV <- reactiveValues(list = NULL)
observeEvent(input$deselect, {
runjs("$('#tree').jstree().deselect_all()")
})
observeEvent(input$savesele, {
session$sendCustomMessage("saveselection", message)
})
observeEvent(input$restoresele, {
req(input$treeselection)
tmp <- paste0("[", paste(input$treeselection, collapse = ","), "]")
js <- sprintf("$('#tree').jstree().select_node(%s)", tmp)
runjs(js)
})
}
shinyApp(ui, server)
Related
I am new to Gatling and scala. facing issue on passing jsonpath saved variable from one repeat section to another forEach repeat section.
following variable "dcIds" is not able to pass to forEach section. Also please direct me to make the below code more better.
var dcIdd = ""
val r = new scala.util.Random
def orderRef() = r.nextInt(100)
def getCreateRequest: String = {
val data = s"""
[{
"name":"DC_${orderRef()}",
"location":"Seattle, Washington, USA",
"type":"Colocation"
}]
""".stripMargin
data
}
def createAppRequest: String = {
val data = s"""
[{
"name":"App_${orderRef()}",
"owner":"a#a.com",
"dataCenterId":"${dcIdd}",
"strategy":"Rehost",
"migrationStrategy":"Rehost"}]
}]
""".stripMargin
data
}
val scn = scenario("Add DC")
.repeat(DcIterations, "index") {
exec(
http("List_plans")
.get(uri2 + "?plan_id=")
.headers(headers_sec)
.resources(
http("DC add")
.post(uri2)
.headers(headers_sec)
.body(StringBody(session => getCreateRequest))
.check(jsonPath("$.ids[*]").findAll.saveAs("dcIds"))))
}
.foreach("${dcIds}", "dcId") {
dcIdd = "${dcId}"
repeat(AppIterations, "index") {
exec(http("Add Application")
.post(uri1 + "/applications/${dcId}")
.headers(headers_sec)
.body(StringBody(session => createAppRequest))
)
}
}
I am using highcharter library. I want to split (or filter) other charts and tables based on selection in particular category of pie (doughnut) chart. My below code is working fine.
Desired result - When user clicks on pie again after selection, it should remove filtering. Below code captures last clicked category and it matches with the current selection using curre() and lstre() reactive values.
Issue When user clicks on pie more than twice, last clicked category matches with the current selected category so it does not perform any filtering.
I tried hc_add_event_point(event = "unselect"), it does not let user select particular category of pie more than twice.
library("shiny")
library("highcharter")
library(dplyr)
ui <- shinyUI(
fluidPage(
column(width = 8, highchartOutput("hcontainer", height = "500px")),
column(width = 4, textOutput("text")),
column(width = 4, dataTableOutput('temptable')))
)
server <- function(input, output) {
a <- data.frame(b = LETTERS[1:5], c = 11:15)
aa <- data.frame(b = LETTERS[1:5])
output$hcontainer <- renderHighchart({
canvasClickFunction <- JS("function(event) {Shiny.setInputValue('canvasClicked', [this.name, event.point.name, Math.random()]);}")
legendClickFunction <- JS("function(event) {Shiny.setInputValue('legendClicked', this.name);}")
highchart() %>%
hc_chart(type="pie") %>%
hc_add_series_labels_values(labels = a$b, values = a$c,
innerSize = '60%',
allowPointSelect= TRUE,
slicedOffset = 20,
states = list(
select = list(
color= NULL,
borderWidth = 5,
borderColor = '#ccc'
))) %>%
hc_plotOptions(series = list(
events = list(click = canvasClickFunction,
legendItemClick = legendClickFunction))) %>%
hc_add_event_point(event = "unselect")
})
makeReactiveBinding("outputText")
rv <- reactiveValues(lstval=0,curval=0)
observeEvent(input$canvasClicked[2], {
rv$lstval <- rv$curval;
rv$curval <- input$canvasClicked[2]}
)
curre <- reactive({req(input$canvasClicked[2]); input$canvasClicked[2]; rv$curval})
lstre <- reactive({req(input$canvasClicked[2]); input$canvasClicked[2]; rv$lstval})
observeEvent(input$canvasClicked, {
outputText <<- paste0("You clicked on series ", input$canvasClicked[1], " and the bar you clicked was from category ", input$canvasClicked[2],
input$plot_hc_unselect, ".")
})
observeEvent(input$legendClicked, {
outputText <<- paste0("You clicked into the legend and selected series ", input$legendClicked, ".")
})
output$text <- renderText({
outputText
})
output$temptable <- renderDataTable(
if (length(input$canvasClicked[2])>0) {
if (curre()!=lstre())
aa %>% filter(b==input$canvasClicked[2])
else {
aa
}
}
else {aa}
)
}
shinyApp(ui, server)
EDIT: Just got the same behavior on 3.4
EDIT2: If I remove the disableLosslessIntegers from the connection the issue goes away, but the all integer numbers come back as {low: 20, high:0} type structures which breaks my entire application
The following code works fine on neo4j 3.3 using the 1.7.2 neo4j-driver for node:
import {v1 as neo4j} from 'neo4j-driver';
const url: string = process.env.COREDB_URL || '';
const user: string = process.env.COREDB_USERNAME || '';
const password: string = process.env.COREDB_PASSWORD || '';
const driver = neo4j.driver(url, neo4j.auth.basic(user, password), {disableLosslessIntegers: true});
let connection = driver.session()
async function go() {
let res = await connection.run(`create (b:Banana {tag: 'test'}) return b,id(b) as id`, {});
let b = res.records[0].get('b').properties
console.log('b',b)
let id = res.records[0].get('id')
console.log('id',id)
res = await connection.run(`MATCH (u) where id(u)=$id return u as id`, {id: id});
console.log(res.records)
let id2 = res.records[0].get('id').properties;
console.log('id2',id2)
}
go().then(() => console.log('done')).catch((e) => console.log(e.message))
it gives the following output:
> node tools\test-id.js
b { tag: 'test' }
id 1858404
[ Record {
keys: [ 'id' ],
length: 1,
_fields: [ [Node] ],
_fieldLookup: { id: 0 } } ]
id2 { tag: 'test' }
done
Under 3.5.1 it does not work. The second statement returns no records:
> node tools\test-id.js
b { tag: 'test' }
id 1856012
[]
Cannot read property 'get' of undefined
BTW, the reason I need to do the get by id right after the create is that I am using an apoc trigger to add things to the node after creation, and apoc triggers apparently run after the object is created and returned, so I need the second get to see the transformed node.
But, for this distilled example I removed the trigger from my DB to ensure that it was not causing the issue
Below is a simplified version of my code. I'm simply trying to get Shiny to pass an input value to an rmongodb query, run the query based on the user input, and then plot the mean of a variable. The code below includes everything needed to replicate my issue, including insertion of documents into the collection.
I'd be very grateful for any help! I'm pulling my hair out (and there wasn't much left to begin with). I suspect that I'm placing the reactive() command inappropriately or something along those lines.
Many thanks to whoever can provide assistance.
#Install required packages and call each
library(devtools)
install_github(repo = "mongosoup/rmongodb")
library(rmongodb)
library(shiny)
#Establish connection with mongodb, check status, name database and collection, insert some documents, return one document
mongo <- mongo.create()
mongo.insert(mongo, "simpledb.main",'{"user":"Joe", "age":34}')
mongo.insert(mongo, "simpledb.main",'{"user":"Joe", "age":31}')
mongo.insert(mongo, "simpledb.main",'{"user":"Joe", "age":53}')
mongo.insert(mongo, "simpledb.main",'{"user":"Kate", "age":29}')
mongo.insert(mongo, "simpledb.main",'{"user":"Lisa", "age":21}')
mongo.insert(mongo, "simpledb.main",'{"user":"Henry", "age":34}')
mongo.insert(mongo, "simpledb.main",'{"user":"David", "age":43}')
if(mongo.is.connected(mongo) == TRUE) {
help("mongo.count")
mongo.count(mongo, "simpledb.main")
}
if(mongo.is.connected(mongo) == TRUE) {
mongo.find.one(mongo, "simpledb.main")
}
#Code needed for Shiny UI
ui <- fluidPage(
fluidRow(
column(2, textInput(inputId = "userName", label = "", value = "Enter name here"))),
mainPanel(plotOutput(outputId = "main_plot"))
)
#Code needed for Shiny server
server <- function(input, output) {
queryReactive <- reactive({
nameFinal <- paste0(input$userName)
query = mongo.bson.buffer.create()
mongo.bson.buffer.append(query, "user", nameFinal)
query = mongo.bson.from.buffer(query)
})
#Run the query and store results as an R list object
queryresults <- mongo.find.all(mongo=mongo, ns = coll, query=queryReactive)
#Convert the R list object into a data frame
resultsdf <- data.frame(matrix(unlist(queryresults), nrow=length(queryresults), byrow=T), stringsAsFactors=FALSE)
output$main_plot <- renderPlot({boxplot(as.numeric(resultsdf$X3))})
}
#Code needed to call Shiny UI and server
shinyApp(ui = ui, server = server)
There is no need for a reactive command in your server function. I have simplified and corrected your function below:
server <- function(input, output) {
output$main_plot <- renderPlot({
nameFinal <- paste0(input$userName)
query = mongo.bson.buffer.create()
mongo.bson.buffer.append(query, "user", nameFinal)
query = mongo.bson.from.buffer(query)
queryresults <- mongo.find.all(mongo=mongo, ns = "simpledb.main", query=query)
if (length(queryresults) > 0) {
resultsdf <- data.frame(matrix(unlist(queryresults), nrow=length(queryresults), byrow=T), stringsAsFactors=FALSE)
boxplot(as.numeric(resultsdf$X3))
}
else boxplot(c(0))
})
}
I have one drop-down and a jQDateRangeSlider(a jQuery widget) in index.gsp of my Grails app.I am posting the value selected in the dropdown and the range selected over the slider to a query in my controller using remoteFunction.I want these three values(2 values from the slider and one value from the drop-down) to be posted to the controller when either of the following events occur:
Drop-down changes
Values over the slider change
The remoteFunction works fine from the onChange of the drop-down but when I replicate the remoteFunction inside the UserValuesChanged block of the slider, it throws an error.This is how my code looks like:
Controller
class PgtypController {
def ajaxGetMv = {
def pgtyp = Pgtyp.executeQuery("select p.date_hour ,p.visits, p.mv, p.browser,p.pagetype,p.platform,p.device,p.time_period from Pgtyp p where p.mv = ? and p.date_hour >= ? and p.date_hour <= ? order by col_0_0_ asc ",[ params.mv ] + params.list( 'date_hour' ))
render pgtyp as JSON
}
def dataSource
def datejson = {
def sql = new Sql(dataSource)
def rows = sql.rows("select min(date_hour) as a , max(date_hour) as b from pgtyp")
sql.close()
render rows as JSON
}
def index() {
}
GSP
<form>
<g:select from="['AFFILIATES', 'CSE','DISPLAYADS','EMAIL','MOBILEWEB','OTHERS','ORGANIC','SEO', 'SEM']" name="mv" id = "mv"
onchange="${remoteFunction(
controller:'Pgtyp',
action:'ajaxGetMv',
params:'\'mv=\' + escape(this.value)+\'&date_hour=\'+ z+\'&date_hour=\'+ b',
//params:'\'mv=\'+this.value',
onSuccess: 'printpgtyp(data)')}"
></g:select>
</form>
<script>
dataFile = "http://localhost:8080/marchmock2/Pgtyp/datejson";
d3.json(dataFile, function(error,data) {
if (data)
dataset = data;
var min = dataset[0].a;
var min2 = new Date(min);
var max = dataset[dataset.length - 1].b;
var max2 = new Date(max);
function addZero(val) {
if (val < 10) {
return "0" + val;
}
return val;
}
var s = $j("#slider").dateRangeSlider({
bounds: {
"min": min2,
"max": max2
},
range: {
min: {
hours: 1
}
},
formatter:function(val){
var m = moment(val);
return m.format("DD/MM/YYYY HH:00:00 ");
},
defaultValues:{
min: min2,
max: max2
}
});
x = (s.dateRangeSlider("values").min);
x.setMinutes(0);
x.setSeconds(0);
z = x.getFullYear()+'-'+(x.getMonth()+1)+ '-'+x.getDate()+' '+x.getHours()+':'+'00'+':'+'00' ;
var y = (s.dateRangeSlider("values").max);
y.setMinutes(0);
y.setSeconds(0);
b = y.getFullYear()+'-'+(y.getMonth()+1)+ '-'+y.getDate()+' '+y.getHours()+':'+'00'+':'+'00' ;
$j('#slider').on("userValuesChanged",function (e, data) {
var x = datavalues.min;
x.setMinutes(0);
x.setSeconds(0);
z = x.getFullYear()+'-'+(x.getMonth()+1)+ '-'+x.getDate()+' '+x.getHours()+':'+'00'+':'+'00' ;
var last = data.values.max;
last.setMinutes(0);
last.setSeconds(0);
b = last.getFullYear()+'-'+(last.getMonth()+1)+ '-'+last.getDate()+' '+last.getHours()+':'+'00'+':'+'00' ;
${remoteFunction(
controller:'Pgtyp',
action:'ajaxGetMv',
params:'\'mv=\' +$(\'mv\').value+\'&date_hour=\'+ z+\'&date_hour=\'+ b',
onSuccess: 'printpgtyp(data)')}
})
});
function printpgtyp(data)
{
console.log(data)
console.log(data.length)
}//end of printpgtyp
</script>
This however gives an error like this:
Uncaught SyntaxError: Unexpected token &
Can anyone tell me where exactly am I going wrong? If the code is working fine inside onChange of select tag then why am I getting this error inside UserValuesChanged of the slider?