I'm wondering if it is possible to create a subset of uneditable leaf nodes with {jsTreeR}.
The expected behaviour for the leafs is, that they can't be:
- renamed
- deleted
- have own child nodes
Moreover, branch nodes should not be deleted if they have leafs. However the leafs can be dragged and dropped among branch or parent nodes.
I've found the option state = list(disabled = TRUE)
but this doesn't seem to affect the context menu:
library(jsTreeR)
library(shiny)
nodes <- list(
list(
text = "Branch 1",
state = list(opened = TRUE, disabled = FALSE),
type = "parent",
children = list(
list(text = "Leaf A", type = "child", state = list(disabled = TRUE), data = list(customdata = 1)),
list(text = "Leaf B", type = "child", state = list(disabled = FALSE), data = list(customdata = 2)),
list(text = "Leaf C", type = "child", state = list(disabled = FALSE), data = list(customdata = 3)),
list(text = "Leaf D", type = "child", state = list(disabled = FALSE), data = list(customdata = 4))
)
),
list(text = "Branch 2", type = "parent", state = list(opened = TRUE))
)
ui <- fluidPage(
jstreeOutput("jstree")
)
server <- function(input, output, session){
output[["jstree"]] <- renderJstree({
suppressMessages(jstree(
nodes,
search = list(
show_only_matches = TRUE,
case_sensitive = FALSE,
search_leaves_only = FALSE
),
dragAndDrop = TRUE,
multiple = TRUE,
contextMenu = TRUE,
types = list(default = list(icon = "fa fa-caret-right"), child = list(icon = "fa-solid fa-leaf"), parent = list(icon = "fa-brands fa-pagelines")),
theme = "proton"
))
})
}
shinyApp(ui, server)
Any hint is appreciated.
Edit: @StéphaneLaurent's approach wrapped in a shiny app:
library(jsTreeR)
library(shiny)
nodes <- list(
list(
text = "Branch 1",
state = list(opened = TRUE, disabled = FALSE),
type = "parent",
children = list(
list(text = "Leaf A", type = "undeletable", state = list(disabled = FALSE), data = list(customdata = 1)),
list(text = "Leaf B", type = "undeletable", state = list(disabled = FALSE), data = list(customdata = 2)),
list(text = "Leaf C", type = "undeletable", state = list(disabled = FALSE), data = list(customdata = 3)),
list(text = "Leaf D", type = "undeletable", state = list(disabled = FALSE), data = list(customdata = 4))
)
),
list(text = "Branch 2", type = "parent", state = list(opened = TRUE))
)
ui <- fluidPage(
jstreeOutput("mytree")
)
customMenu <- JS(
"function customMenu(node) {",
" var tree = $('#mytree').jstree(true);", # 'mytree' is the Shiny id or the elementId
" var items = {",
" 'delete' : {",
" 'label' : 'Delete',",
" 'action' : function (obj) { if(node.type !== 'undeletable') tree.delete_node(node); },",
" 'icon' : 'glyphicon glyphicon-trash'",
" }",
" }",
" return items;",
"}")
server <- function(input, output, session){
output[["mytree"]] <- renderJstree({
suppressMessages(jstree(
nodes,
search = list(
show_only_matches = TRUE,
case_sensitive = FALSE,
search_leaves_only = FALSE
),
dragAndDrop = TRUE,
multiple = TRUE,
contextMenu = list(items = customMenu),
types = list(default = list(icon = "fa fa-caret-right"), undeletable = list(icon = "fa-solid fa-leaf"), parent = list(icon = "fa-brands fa-pagelines")),
theme = "proton"
))
})
}
shinyApp(ui, server)