8 Replies Latest reply on Aug 13, 2018 6:41 AM by 3758340

    Apex 18.1 using Checkboxes in a tree

    3758340

      Good afternoon.

      I have a question about the new tree region (with Checkboxes) in Apex 18.1 :

      I would like that, when I select a node, also all its ancestors are selected. I have tried but I am not able to do this.

       

      Is it possible or is this function not foreseen?

       

       

      Thanks.

      Best regards.

      Cinzia

        • 1. Re: Apex 18.1 using Checkboxes in a tree
          MiroMas

          I started from checkbox tree mentioned here: Add Checkbox Selection to APEX Tree Region – HardLikeSoftware . Note you can download test app.

          I changed Javascript code for Checkbox tree page (Execute on page Load). You can check result here: https://apex.oracle.com/pls/apex/f?p=104351:2

          Maybe it's not exactly what you need but it's simmilar.

          The latest version of treeView widget API is used. I guess you need APEX 18.1. for this code to work. API doc: https://docs.oracle.com/database/apex-18.1/AEXJS/treeView.html

          Changed Code:

           

          var tree$ = $("#mytree"), // change this to use whatever id you give the tree
              nodeAdapter = tree$.treeView("getNodeAdapter");

          // Set a custom node renderer that adds a checkbox icon span
          nodeAdapter.renderNodeContent = function( node, out, options, state ) {
              out.markup("<span class='treeSelCheck'></span>"); // this is the checkbox - its not a real checkbox input
              // the rest of this code is essentially a copy of what is in widget.treeView.js function renderTreeNodeContent
              if ( this.getIcon ) {
                  icon = this.getIcon( node );
                  if ( icon !== null ) {
                      out.markup( "<span" ).attr( "class", options.iconType + " " + icon ).markup( "></span>" );
                  }
              }
              link = options.useLinks && this.getLink && this.getLink( node );
              if ( link ) {
                  elementName = "a";
              } else {
                  elementName = "span";
              }
              out.markup( "<" + elementName + " tabIndex='-1' role='treeitem'" ).attr( "class",options.labelClass )
                  .optionalAttr( "href", link )
                  .attr( "aria-level", state.level )
                  .attr( "aria-selected", state.selected ? "true" : "false" )
                  .optionalAttr( "aria-disabled", state.disabled ? "true" : null )
                  .optionalAttr( "aria-expanded", state.hasChildren === false ? null : state.expanded ? "true" : "false" )
                  .markup( ">" )
                  .content( this.getLabel( node ) )
                  .markup( "</" + elementName + ">" );   
             
                  //window.alert('nodeAdapter.renderNodeContent '+ this.getLabel( node ) +' '+ node.id);
          };

          tree$.treeView("option","multiple", true) // make the tree support multiple selection
              .treeView("refresh") // refresh so that all the nodes are redrawn with custom renderer
              .on("click", ".treeSelCheck", function(event) { // make that "checkbox" span control the selection
                  var nodeContent$ = $(event.target).closest(".a-TreeView-content"),
                      isSelected = nodeContent$.hasClass("is-selected"),
                      selection$ = tree$.treeView("getSelectedNodes"),
                      node$ = tree$.treeView("getNodes", nodeContent$)[0];
             
                  function remove(arr, item) {
                    var index = arr.indexOf(item);
                    if (index > -1) {
              arr.splice(index, 1);
              }
                  };

                  if ( isSelected ) {
                      remove(selection$,node$);
                      //naredi za vse otroke
                      for (i = 0; node$.children && i < node$.children.length; i++) {
                        remove(selection$, node$.children[i]);
                      }
                  } else {
                      selection$.push(node$);
                      //naredi za vse otroke
                      for (i = 0; node$.children && i < node$.children.length; i++) {
                        selection$.push(node$.children[i])
                      }
                  }
                  tree$.treeView("setSelectedNodes", selection$);
                  $s("P2_SELECTED_NODES", selection$.map(function(n) {return n.id;}).join(":"));
                  //window.alert('setSelectedNodes - onClick');
                  return false; // stop propagation and prevent default
              });

          tree$.treeView("option", "selectionChange", function(e){
                  var nodes = $("#mytree").treeView("getSelection");
            //$s("P2_SELECTED_NODES", nodes.map(function(n) {return n.id;}).join(":"));
                  tree$.treeView("setSelectedNodes", $v("P2_SELECTED_NODES").split(":").map(function(i) {
                      //window.alert('setSelectedNodes - selectionChange');   
                      return { id: i };
                  }));
                  //tree$.treeView("collapse", nodes);
                  ////window.alert('selectionChange');
          });

          // setSelectedNodes only works if the node has been rendered so do expand all
          // this is not ideal but much simpler than having to check each node and expand parents as neeeded, remove if not needed
          tree$.treeView("expandAll");
          tree$.treeView("setSelectedNodes", $v("P2_SELECTED_NODES").split(":").map(function(i)
          { //window.alert('setSelectedNodes');
            return { id: i }; }));
          //window.alert('setSelectedNodes construktor');

          • 2. Re: Apex 18.1 using Checkboxes in a tree
            3758340

            Thanks you, MiroMas.

            I will do what you have suggested even if my need is the opposite of what I should get with your script (I need to select a leaf and have automatically selected his ancestors).

             

            Ciao

            Cinzia

            • 3. Re: Apex 18.1 using Checkboxes in a tree
              hafferl

              I have exactly the same question, how can you select all ancestors if you select a parent node?

              • 4. Re: Apex 18.1 using Checkboxes in a tree
                MiroMas

                I'm not JS or JQuery expert but you need to replace code:

                 

                if ( isSelected ) {
                            remove(selection$,node$);
                            //this is for each children, replace with while loop
                            for (i = 0; node$.children && i < node$.children.length; i++) {
                              remove(selection$, node$.children[i]);
                            }
                        } else {
                            selection$.push(node$);
                            //this is for each children, replace with while loop
                            for (i = 0; node$.children && i < node$.children.length; i++) {
                              selection$.push(node$.children[i])
                            }

                 

                WITH:


                if ( isSelected ) {
                  remove(selection$,node$);
                  while node$.parent{
                   node$ = $node.parent;
                    remove(selection$, node$);
                }
                }
                else {
                  selection$.push(node$);
                  while node$.parent{
                   node$ = $node.parent;
                    selection$.push(node$);
                }

                 

                Something like that

                HTH

                Miro

                • 5. Re: Apex 18.1 using Checkboxes in a tree
                  tirone

                  Thanks you, Miro,

                  I have exactly the same question.

                   

                  A few weeks ago I opened a threed about the same problem (Apex 18.1 tree with  Checkboxes - select all ancestor ), but I had no answer ..
                  I did some tests using your script and your suggestions but, at the moment, I could not get what I wanted. (selecting a tree leaf to have all his ancestors selected).

                  Also I am not an expert in JS and JQuery, but trying your code I verified that:

                  • in the first case (your first answer to Cinzia) when selecting a node I want to have all his descendants selected, I get only the first level of the children and not all.
                  • In the second case (your second response to Cinzia) when selecting a node I want to have all of its ancestors selected, I have verified that the "parent" property of the node does not exist.

                   

                  Looking at the treeView Widget documentation it seems that the node property is "_parent" and not parent.

                  Changing this property into your code ..

                  ......

                  if ( isSelected ) {

                    remove(selection$,node$);

                    while (node$._parent) {

                      node$ = $node._parent;

                      remove(selection$, node$);

                  }

                  }

                  else {

                    selection$.push(node$);

                    while (node$._parent){

                      node$ = $node._parent;

                      selection$.push(node$);

                  }

                  }

                  .......

                   

                  now seems that the parent node object exists, but the statement:

                  node$ = $node._parent

                  is not correct and after this assignement i get the following error in the console

                  ReferenceError: $node is not defined

                   

                  We hope that some expert can help us

                   

                  in any case, many thanks for your suggestions

                  saverio

                  • 6. Re: Apex 18.1 using Checkboxes in a tree
                    MiroMas

                    I'm not JS or JQuery expert but it was just typewriting error ($node instead of node$). Correct code is:

                     

                    if ( isSelected ) {

                                  remove(selection$,node$);

                                  while (node$._parent) {

                                      node$ = node$._parent;

                                      remove(selection$, node$);

                                  }

                            }

                            else {

                              selection$.push(node$);

                              while (node$._parent){

                                node$ = node$._parent;

                                selection$.push(node$);

                              }

                            }

                     

                    Hope it works like expected: https://apex.oracle.com/pls/apex/f?p=104351:2

                    • 7. Re: Apex 18.1 using Checkboxes in a tree
                      tirone

                      Thank you so much Miro now it works!
                      Even I did not notice the trivial typewriting error 

                      Thanks again
                      Saverio

                       

                       

                      • 8. Re: Apex 18.1 using Checkboxes in a tree
                        3758340

                        Thanks for your help. Now it works.

                         

                        Cinzia