jsTree

Tree Control

{
  "id": "costCenterTree",
  "controlType": "htmlTemplate",
  "refersToConfigSource": "",
  "htmlTemplateContent": "<style>\r\n    .bbjsTree{\r\n        \r\n    }\r\n</style>\r\n<input type=\"text\" value=\"\" class=\"input ccTreeSearch\" style=\"margin:0em auto 1em auto; display:block; padding:4px; border-radius:4px; border:1px solid silver;\" />\r\n<div class=\"bbjsTree\" id=\"tree\"></div>",
  "events": [
    {
      "name": "onSubDataRequest",
      "code": "debugger;\r\n//Lib laden, wenn noch nicht passiert\r\nif (!window.jsTree) {\r\n    $('head').append(`<link href=\"https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css\" rel=\"stylesheet\">`);\r\n    await jQuery.getScript(\"https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js\");\r\n    window.jsTree = true;\r\n}\r\n//Daten und HTML Elemente besorgen\r\nlet ccResult = app.sqlRead(\"getAllCostcentersForTree\");\r\nlet treeElement = $(app.getHtmlElement(\"costCenterTree\")).find(\".bbjsTree\");\r\nlet searchInput = $(app.getHtmlElement(\"costCenterTree\")).find(\".ccTreeSearch\");\r\n\r\n//Daten transformieren, könnte auch schon in sql passieren.\r\nlet ccTreeData = ccResult.map(x => {\r\n    return {\r\n        id: x.id,\r\n        text: x.ccName,\r\n        parent: x.ccParentId ? x.ccParentId : \"#\"\r\n    };\r\n});\r\n\r\n//Alten tree zerstören\r\ntreeElement.jstree(\"destroy\");\r\n\r\n//Events verknüpfen und tree Erzeugen\r\ntreeElement\r\n    .on('create_node.jstree', async function (e, newNode, position) {//wenn Context Menu Create geklickt wurde\r\n        let createApp = app.startBrixxbox({\r\n            appName: \"costCenter\",\r\n            additionalValues: {\r\n                ccParentId: newNode.parent,\r\n                ccName: newNode.node.text\r\n            },\r\n        });\r\n        await createApp.addEventListener(\"onRecordSaved\", function (brixxApi, eventArgs) {\r\n            app.refresh(\"costCenterTree\");\r\n        })\r\n    })\r\n    .on('changed.jstree', function (e, data) {\r\n        for (let i = 0; i < data.selected.length; i++) {\r\n            console.log(\"Selected: \" + data.instance.get_node(data.selected[i]).text)\r\n        }\r\n    })\r\n    .jstree({\r\n        'core': {\r\n            \"check_callback\": true,\r\n            \"data\": ccTreeData,\r\n            \"themes\": {\r\n                \"variant\": \"large\"\r\n            }\r\n        },\r\n        \"checkbox\": {\r\n            \"keep_selected_style\": false\r\n        },\r\n        \"plugins\": [\"wholerow\",  \"dnd\", \"search\", \"contextmenu\"]\r\n        //\"checkbox\",\r\n    });\r\n\r\n//Suchfeld Events verknüpfen\r\nlet to = false;\r\nsearchInput.keyup(function () {\r\n    debugger;\r\n    if (to) { clearTimeout(to); }\r\n    to = setTimeout(function () {\r\n        var v = searchInput.val();\r\n        treeElement.jstree(true).search(v);\r\n    }, 250);\r\n});"
    }
  ],
  "index": 14
}

Copy the code below as a Control in your App Config. Make adjustments to the onSubDataRequest event for your specific usecase and render the control with app.refresh("myTree") at any point.

Take a look at https://www.jstree.com/ for further configuration details and options.

Example JSON Structure from jsTree

// Alternative format of the node (id & parent are required)
{
  id          : "string" // required
  parent      : "string" // required
  text        : "string" // node text
  icon        : "string" // string for custom
  state       : {
    opened    : boolean  // is the node open
    disabled  : boolean  // is the node disabled
    selected  : boolean  // is the node selected
  },
  li_attr     : {}  // attributes for the generated LI node
  a_attr      : {}  // attributes for the generated A node
}

Last updated