Using TreeView control in ESS Portal

Alex Ng
Tera Contributor

Hi experts,

I wanted to create a 3-tier tree view for knowledge base documents or policies in ServiceNow ESS. For example, 1st tier will be country, 2nd tier will be department and 3rd tier will show sub-department with breakdown of documents related to that sub-documents.  


3Tier.png

Is this possible or has anyone has any ideas how to do it? Thank you for your time/

1 ACCEPTED SOLUTION

tltoulson
Kilo Sage

Hi Alex,



There are a number of options and approaches for this depending on your requirements:



1.   Reuse the GwtTree2 that ServiceNow uses elsewhere in the system: Cool UI Page


2.   Create your own entirely server side in Jelly (will have performance problems on large trees or deep nesting)


3.   Create your own using some client side script or framework you import in (jsTree or angular.js for instance)



I have done #2 and #3 in the past, never tried #1 because I can't control if ServiceNow drops GwtTree in favor of something else.   I can control scripts that I import.   Use ServiceNow's tree picker as an example or the UI Page in the link above.   ServiceNow loads the first level of the tree and then loads subsequent levels only one node at a time as you expand the nodes.   This is best for performance on larger trees.



The HTML for these trees can be done either with a <table> or <ul><li> format.   So really, you are just running an initial GlideRecord to get the first tier.   Then each time a '+' is clicked, if the node hasn't been loaded, run a GlideRecord query to get all records with the parent you just clicked.



I hope that helps.   Let me know if you need more information.


View solution in original post

5 REPLIES 5

tltoulson
Kilo Sage

Hi Alex,



There are a number of options and approaches for this depending on your requirements:



1.   Reuse the GwtTree2 that ServiceNow uses elsewhere in the system: Cool UI Page


2.   Create your own entirely server side in Jelly (will have performance problems on large trees or deep nesting)


3.   Create your own using some client side script or framework you import in (jsTree or angular.js for instance)



I have done #2 and #3 in the past, never tried #1 because I can't control if ServiceNow drops GwtTree in favor of something else.   I can control scripts that I import.   Use ServiceNow's tree picker as an example or the UI Page in the link above.   ServiceNow loads the first level of the tree and then loads subsequent levels only one node at a time as you expand the nodes.   This is best for performance on larger trees.



The HTML for these trees can be done either with a <table> or <ul><li> format.   So really, you are just running an initial GlideRecord to get the first tier.   Then each time a '+' is clicked, if the node hasn't been loaded, run a GlideRecord query to get all records with the parent you just clicked.



I hope that helps.   Let me know if you need more information.


Hi Travis,



Thanks for the detail explanation. As I am new to this, do you think you can verify my steps below? Just wanted to make sure I am on the right track.



Let's say I want to use Knowledge Base articles module in the ESS portal with jsTree. So basically, each articles will have a category and the treeview control will be categorized based on the category. Since I am implementing this in ESS module, my steps would be the following:



1) Download the jsTree package


2) Import the related js files from the jsTree package into ServiceNow as Macro


3) Under Content Management, go to Blocks, then, create a new Dynamic content.


4) Include all library links of jsTree in the XML box


5) Start writing logic to fetch Knowledge Base content using GlideRecord query in the XML box



Are my steps above correct? Do correct me if I miss out anything. Thank you for your help.


Hi Alex,



I would change one thing.   Although you can certainly import jsTree as a Macro, you would be better off importing it as a UI Script.   Then you would use either the <g:requires> tag or the <script> tag to include it in your Dynamic Block as seen here.



That is the only part I would change, everything else is exactly right.   Some other guidelines, you will probably use <g:evaluate> to do at least the query for the first tier and you will need to pass the results to the client so jsTree can use it.   Here is a brief option for doing that:



<g:evaluate>


        var treeNodes = []; // This should be an object or an array that describes at least the first tier of the tree, this will get passed to the client


        var gr = new GlideRecord('kb_knowledge');


        // gr.addQuery type code here


        gr.query();


        while (gr.next) {


                  treeNodes.push({ name: gr.title, id: gr.sys_id }); // At a minimum you will need to pass a display value (title) and the id of the record


        }



        treeNodes = new JSON.encode(treeNodes); // Converts the whole object to a string, which can be passed to the client and reinterpreted as an object


</g:evaluate>


<script>


        // Script tags are part of HTML and are processed client side, not server side


        var treeNodes = JSON.parse("${treeNodes}"); // parses the JSON created above and makes the object available to the client


        // You can do jsTree stuff here


<script>



That may not be exactly right but it should get you on the right path.   I hope this helps.



Kind regards,



Travis


Hi Travis,



Thank you for your help. I will try this out.



Regards,


Alex