How to remove the option for the user to collapse a specified parent node in jsTreeR?

46 views Asked by At

Any recommendations for how to make only specific nodes in package jsTreeR non-collapsible, while all other nodes remain collapsible as illustrated below? The code is posted beneath the illustration.

enter image description here

Code:

library(jsTreeR)
library(shiny)

nodes <- list(
  list(
    text = "Menu",
    state = list(opened = TRUE),
    children = list(
      list(text = "Dog",type = "moveable",state = list(disabled = TRUE)),
      list(text = "Cat",type = "moveable",state = list(disabled = TRUE))
    )
  ),
  list(text = ">> Drag here <<",type = "target",state = list(opened = TRUE))
)

dnd <- list(
  always_copy = TRUE,
  inside_pos = "last", 
  is_draggable = JS(
    "function(node) {",
    "  return node[0].type === 'moveable';",
    "}"
  )
)

mytree <- jstree(
  nodes, dragAndDrop = TRUE, dnd = dnd,
  types = list(moveable = list(), target = list())
)

ui <- fluidPage(
  # tags$head(tags$script(HTML(script))),
  fluidRow(jstreeOutput("mytree"))
)

server <- function(input, output, session){output[["mytree"]] <- renderJstree(mytree)}

shinyApp(ui, server)
2

There are 2 answers

1
thothal On BEST ANSWER

I would add a direct click handler to the first <i> node, which uses stopPropagation to prevent the click event to bubbling up and thus closing the parent. You need to delay the assignment of the click handler, b/c at render time the nodes (and thus the <i> element with the arrow) are not yet set up. An outer one handler fires, when the nodes are ready and that’s where we assign the click handler.

mytree %>%
   htmlwidgets::onRender("
      function (el) {
         $(el).one('ready.jstree', function() { 
             // need to wait until all nodes are loaded to assigne event listener
             $(this).find('i').first().on('click', (evt) => evt.stopPropagation()) 
         });
      }")
0
Stéphane Laurent On

Not perfect but works. Set state = list(opened = TRUE, freezed = TRUE) for the nodes you want to prevent the closing.

library(jsTreeR)

dat <- list(
  list(
    text = "RootA",
    data = list(value = 999),
    icon = "glyphicon glyphicon-folder-open",
    state = list(
      opened = TRUE,
      freezed = TRUE
    ),
    children = list(
      list(
        text = "ChildA1",
        icon = "glyphicon glyphicon-file",
        children = list(
          list(
            text = "XXX"
          )
        )
      ),
      list(
        text = "ChildA2",
        icon = "glyphicon glyphicon-file"
      )
    )
  ),
  list(
    text = "RootB",
    icon = "glyphicon glyphicon-folder-open",
    children = list(
      list(
        text = "ChildB1",
        icon = "glyphicon glyphicon-file"
      ),
      list(
        text = "ChildB2",
        icon = "glyphicon glyphicon-file"
      )
    )
  )
)

jstree(dat) %>%
  htmlwidgets::onRender(c(
    "function(el) {",
    "  $(el).on('close_node.jstree', function (e, data) {",
    "    if(data.node.state.freezed) {",
    "      setTimeout(function(){data.instance.open_node(data.node);}, 0);",
    "    }",
    "  });",
    "}"
  ))