Dynamic Content Blocks

Patrick Quinlan
Giga Guru

I am attempting to build a Dynamic Content block to act as an interactive filter. I am trying to construct an assignment group select input that derives it's values from the sys_user_groups table. I feel like I am extremely close to getting this to work, however the only choices that it builds into the select input all state "org.Mozilla.javascript.nativearray....."

It doesn't appear to pull the actual names of the groups from the table. Below is the code that I'm starting with. Obviously, once I can get this portion of code working, I will build on it. Can anyone assist?

<?xml version="1.0" encoding="utf-8" ?>

<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">

<g:evaluate var="jvar_test" object="true" jelly="true">

        var obj=[];

        var gr= new GlideRecord('sys_user_group');

            gr.query();

            while(gr.next()){

                  obj.push(gr.name.getDisplayValue());

            }

        obj;

</g:evaluate>

<select name="AGroup">

  <j:forEach items="${jvar_test}">

          <option value="${jvar_test}"> ${jvar_test} </option>

  </j:forEach>

</select>      

</j:jelly>

1 ACCEPTED SOLUTION

Geoffrey2
ServiceNow Employee
ServiceNow Employee

The main issue is you're missing the var attribute in the forEach loop. items is your Array, and var defines the variable for the individual items in the array.


Think of it like this:



for (jvar_choice in items) {


        // Do stuff


}



<?xml version="1.0" encoding="utf-8" ?>


<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">



        <g:evaluate>


                  var obj = [];


                  var gr= new GlideRecord('sys_user_group');


                  gr.query();


                  while(gr.next()) {


                            obj.push(gr.name.getDisplayValue());


                  }


        </g:evaluate>



        <select name="AGroup">


                  <j:forEach var="jvar_choice" items="${obj}">


                            <option value="${jvar_choice}">${jvar_choice}</option>


                  </j:forEach>


        </select>    



</j:jelly>


View solution in original post

10 REPLIES 10

Patrick Quinlan
Giga Guru

I have two select inputs, one for Delivery Unit and one for Assignment Group. The goal is to be able to pick a Delivery Unit and the make the Assignment group select input only show those assignment groups that fall under the selected Delivery Unit. I currently have the two select inputs working. I have wrapped the g:evaluate for the Assignment group with a function and I call that function with an onChange of the Delivery Unit select input, however it's not working.



<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="jelly:core" xmlns:g2="glide">



          <g:evaluate>


                      var du = [];


                      var dugr= new GlideRecord('u_delivery_units');


                      dugr.query();


                      while(dugr.next()){


                              du.push(dugr.u_name.getDisplayValue());


                      }


      </g:evaluate>



      <script>


              function AGroupFilter(DUvar){


                      <g:evaluate>


                          var obj = [];


                          var gr= new GlideRecord('sys_user_group');


                       


                          gr.query();


                          while(gr.next()) {


                            obj.push(gr.name.getDisplayValue());


                          }


                      </g:evaluate>


             


              }


      </script>              


             


      <select name="DelUnit" onChange = "AGroupFilter('DelUnit.value')" >


              <j:forEach var="jvar_choice" items="${du}">


                      <option value="${jvar_choice}">${jvar_choice}</option>


              </j:forEach>


      </select>



     


      <br/>


      <br/>


     


      <select name="AGroup">


                <j:forEach var="jvar_choice" items="${obj}">


                            <option value="${jvar_choice}">${jvar_choice}</option>


                </j:forEach>


      </select>    


         


     



</j:jelly>


In that example, the <g:evaluate> tags are only being executed once, on the server, when the form loads. The <script> tags are executed in the client. So having <g:evaluate> tags inside <script> tags will not cause the <g:evaluate> to be executed again.   You need to replace those inner <g:evaluate> tags with a standard GlideAjax function - if you really want to do a new GlideRecord every time the first select box changes.



However, I would personally avoid multiple GlideAjax calls and solve the problem like this, by creaing a complete list of values inside an object, called "map", and use it to dynamically change the options in the second select.



<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="jelly:core" xmlns:g2="glide">



        <g:evaluate>


                  var map = {};


                  var duList = [];


                  var duGr, groupGr, id;



                  duGr = new GlideRecord('u_delivery_units');


                  duGr.orderBy('u_name');


                  duGr.query();


                  while (duGr.next()) {


                            id = String(duGr.sys_id);


                            duList.push({"label": duGr.name.getDisplayValue(), "value": id}); // Add to list of Delivery Units


                            map[id] = [];



                            // Get a List of Groups for this Delivery Unit


                            groupGr = new GlideRecord('sys_user_group');


                            groupGr.addQuery('u_delivery_unit', duGr.sys_id); // Assumes Delivery Unit is a Reference field on Group


                            groupGr.orderBy('name');


                            groupGr.query();


                            while (groupGr.next()) {


                                      map[id].push({"label": String(groupGr.name), "value": String(groupGr.sys_id)}); // Add to list of Groups for this Del Unit


                            }


                  }


                  map = JSON.stringify(map); // need a string to pass to the client-side


        </g:evaluate>



        <input type="hidden" id="map" value="${map}" /> <!-- Here is how we pass values from the server to the Client -->



        <script>


                  var map = JSON.parse(jQuery('#map').val()); // retrieve the map



                  // Update the list


                  function DelUnitChanged(newValue) {


                            jQuery('#AGroup option').remove(); // remove all options


                            jQuery('#AGroup').append(jQuery('<option></option>').attr('value', '-').text('-- None --')); // Add -- None --



                            if (newValue) {


                                      var i, option;


                                      for (i = 0; i != map[dulUnitId].length; i++) {


                                                option = map[dulUnitId][i];


                                                // Add Options for the list of Groups


                                                jQuery('#AGroup').append(jQuery('<option></option>').attr('value', option.value).text(option.label));


                                      }


                            }


                  }


        </script>



        <select id="DelUnit" onChange="DelUnitChanged(this.value)" >


                  <option value="">-- None --</option>


                  <j:forEach var="jvar_du" items="${duList}">


                            <option value="${jvar_du.value}">${jvar_du.label}</option>


                  </j:forEach>


        </select>



      <br/>



      <select id="AGroup">


                <option value="">-- None --</option>


      </select>



</j:jelly>


I really hate to keep asking questions, but I have attempted to get this code working and am not having any luck. I had to make a few minor changes to the evaluate script in order for the Delivery Unit field to work, but no matter what I do, it does not populate the Assignment group field. When a DU is selected, it does remove the -NONE- from the assignment group field, but it doesn't successfully populate anything. I'll admit that this code is a little more advanced than what I'm familiar with so I am swimming in unfamiliar waters.



Thank you in advance


You will need to give me more information if you want me to help any further.   I cannot know where your code is breaking if I can't see it. I have made an assumption on line 18 that there is a Reference field on the Group table, called u_delivery_unit.   How are the Groups and Delivery Units related to each other?


I follow all of your code and I have put some stops in to determine where the break is happening. It appears that it is failing at the for loop and I think it may have something to do with the map[dulUnitId] call. "dulUnitId" is only referenced starting at the loop so is it trying to call something that isn't defined?