Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

How exactly do you pass a form value to a UI Macro via an onChange Client Script?

maynartt
Kilo Guru

My requirement is to redisplay available actions based on the value in "work unit type" - when that value changes, new actions associated with it need to appear.   A UI Macro I have developed takes care of this "redisplay:".   This needs to happen before the record with that work unit type is created, therefore server-side code doesn't help me.

Therefore I created a onChange client script (executes onChange of work unit type) with the following code.   What's in bold red calls a function in a UI Macro:

function onChange(control, oldValue, newValue, isLoading, isTemplate) {

      if (newValue === '') {

              // don't show the Work Unit Type Actions form section if work unit type is not yet filled in

              g_form.setSectionDisplay('work_unittypeactions', false);

      } else if (g_form.isNewRecord()) {

              // when the record hasn't been saved yet, and the work unit type changes, we need to wipe out

              // any work unit type actions that may have been selected and saved, and present the actions

              // associated with the new work unit type.

              getWut();

      } // no "else" needed because work unit type is always protected after creation - there is no other way the work unit type can be changed.

}

Function getWut exists in a UI Macro (a copy of its entire xml):

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

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

      <!-- New Records do not have an established work unit type, only existing records do -->

      <g2:evaluate>

              var isNotNewRecord = !current.isNewRecord();

              // gs.info('MACRO-work_unit_type_actions: isNotNewRecord={0}",isNotNewRecord);

      </g2:evaluate>

      <!-- If the record is not new, allow the work unit type actions to show on the form.

              The sys-id of the task group is included

              to be used for retrieval of work unit type actions

              and other needed data within the body and for processing -->

      <j2:if test="$[isNotNewRecord]">

              <tr>

                      <td colspan="2" width="100%" style="padding: 0;">

                              <g2:evaluate var="jvar_sysid">

                                      var sysId = current.sys_id;

                                      sysId;

                                      // gs.info('MACRO-work_unit_type_actions: sysId={0}",sysId);

                              </g2:evaluate>

                              <g:work_unit_type_actions_body />

                      </td>

              </tr>

      </j2:if>

      <j2:if test="$[!isNotNewRecord]">

              <tr>

                      <td colspan="2" width="100%" style="padding: 0;">

                      <script>

                              // called from client script to make new work unit type available

                              function getWut(){

                                      var myWut = g_form.getValue('work_unit_type');

                                      alert('MACRO-work_unit_type_actions: myWut=' + myWut);

                              }

                      </script>

                              <g:work_unit_type_actions_body />

                      </td>

              </tr>

      </j2:if>

</j:jelly>

I have inserted gs.info statements in the work_unit_type_actions_body ui macro that is executed from the above ui macro (and after the getWut function).   The alert appears when I change the value of work unit type on the form (and I do see that myWut has the value I need), and those gs.info statements in work_unit_type_actions_body do indeed write to the log, so I know that it is at least executing.   But for the life of me I can't figure out how to extract the value in myWut and get it to ui macro work_unit_type_actions_body.

I have asked a similar question in Passing the value from client script to UI Macro, for your reference.   This sounds like a similar issue, but how exactly it's done is not explained there.

Note - this is part of a scoped app - i have intentionally removed the scoped app parts of the macro name in the above example.

Thanks!

1 ACCEPTED SOLUTION

maynartt
Kilo Guru

All,



We've assumed, based on Chris' and Slava's answers, that what we're trying to do won't work.  



We were trying to do something fancy by having a change on a form's field trigger angular code to display data related to what that field was changed to.   We've instead replaced this angular functionality with a simple glidelist, which provides for our requirement.    



Thanks everyone.


View solution in original post

7 REPLIES 7

chris_f
Kilo Expert

Hey,


Once the macro loads, it's pretty much "Dead" so passing in values, to make the macro do something isn't possible.



Your client side scripts can, but if you require server data the best bet is possibly to make use of Ajax or G_scratchpad.



What are you trying to achieve, is it that you want a drop down list to show specific options based on the values of a SAVED record?



Plenty of options, I don't think this macro is the best route, but I'm not 100% clear yet on the requirement


Cheers


I replied via email, so I apologize if this will be repeated in this thread...


==============================


Chris — thanks for replying.



Unfortunately, server data can't help me, because the record that the work unit type is on is not yet created.   The user can change that work unit type value several times on the form before that record is created, and each time they change it, I need to display the associated work unit type actions in a separate form section.   Ajax definitely won't help me.   But maybe g_scratchpad can?   I didn't know that g_scratchpad is available to client scripts and ui macros.   Thought it can/should only be used with on display business rules.   Please correct me if I'm wrong.



To answer your second question — what am I trying to do — I can first answer that I'm not trying to show specific options on the value of a SAVED record — my requirement is to show those options before the record is saved.



It might very well be that you're right — that using a macro for this isn't the best option.   I'll give more of an explanation as to what needs to happen in my next reply to Slava.



Rgds,


Tor


Slava Savitsky
Giga Sage

Jelly code in your macro is evaluated server-side when the page is being renderer whereas the onChange client script is executed client-side and at a later point in time. Therefore you cannot pass any values from your client script to your macro. What is inside the "work_unit_type_actions_body" macro? What exactly would you like to happen after getWut() is executed?


I replied to the email, so I apologize if this reply gets repeated in this thread...


============================================================


Slava — thanks for replying.



I've copied the xml from the work_unit_type_actions_body macro below.   What needs to happen is that when the work unit type changes on the form, the work unit type actions associated with that work unit type need to appear in a list in a formatter form field on that same form.   I've done this by using angular, modeled after another similar way of displaying data within our app (to give our users a consistent experience).   When I need to retrieve the data from an existing record (the "if (taskGroup.get(jelly.jvar_sysid)) {" line in the following), it works just great.   But when the record does not yet exist, as I explained before, it needs to base what is being retrieved on the value of work unit type on the form.



Hope this helps explain it — let me know if you need more info.




=========== START OF work_unit_type_actions_body MACRO ========================


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


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


<g2:evaluate jelly='true'>


                              // wutad = Work Unit Type Action Data, wuta = Work Unit Type Action


                              var wutad = [];


                           


                              gs.info('work_unit_type_actions_body: jvar_sysid={0},',jelly.jvar_sysid);



                              var taskGroup = new GlideRecord('task_group');


                              if (taskGroup.get(jelly.jvar_sysid)) {


                           


                                                              // gs.info('work_unit_type_actions_body: exists work_unit_type={0}',taskGroup.work_unit_type.toString());


                           


                                                              var tgwuta = new GlideRecord('m2m_work_unit_ty_task_groups');


                                                              tgwuta.addQuery('task_group',taskGroup.sys_id.toString());


                                                              tgwuta.query();



                                                              while (tgwuta.next()) {



                                                                                              // gs.info('work_unit_type_actions_body: tgwuta sys_id={0}',tgwuta.sys_id.toString());


                           


                                                                                              wutad.push({


                                                                                                                              "tg_exists_in_db":'true',


                                                                                                                              "tg_sys_id":tgwuta.task_group.toString(),


                                                                                                                              "sys_id":tgwuta.work_unit_type_actions.toString(),


                                                                                                                              "work_unit_type_action.short_description": tgwuta.work_unit_type_actions.short_description.toString(),


                                                                                                                              "work_unit_type_action.description": tgwuta.work_unit_type_actions.description.toString(),


                                                                                                                              "create_task":'true',


                                                                                                                              "tg_wuta_sys_id":tgwuta.sys_id.toString()


                                                                                              });



                                                              }


                           


                              } else {


                           


                                                              // gs.info('work_unit_type_actions_body: doesnt exist work_unit_type={0}',taskGroup.work_unit_type.toString());


                           


                                                              var wuta = new GlideRecord('work_unit_type_actions');


                                                              wuta.addQuery('work_unit_type',taskGroup.work_unit_type.toString());   //NEEDS TO BE CHANGED TO GET THE WORK UNIT TYPE FROM THE FORM


                                                              wuta.addQuery('active_indicator',true);


                                                              wuta.query();



                                                              while (wuta.next()) {



                                                                                              // gs.info('work_unit_type_actions_body: wuta sys_id={0}',wuta.sys_id.toString());


                           


                                                                                              wutad.push({


                                                                                                                              "tg_exists_in_db":'false',


                                                                                                                              "tg_sys_id":taskGroup.sys_id.toString(),


                                                                                                                              "sys_id":wuta.sys_id.toString(),


                                                                                                                              "work_unit_type_action.short_description": wuta.short_description.toString(),


                                                                                                                              "work_unit_type_action.description": wuta.description.toString(),


                                                                                                                              "create_task":'false',


                                                                                                                              "tg_wuta_sys_id":''


                                                                                              });



                                                              }


                           


                              }



                              var wutadString = global.JSON.stringify(wutad);


                           


                              // gs.info('work_unit_type_actions_body: wutadString={0}',wutadString);



</g2:evaluate>



<div data-ng-app="tskGrpActnsApp" data-ng-init="tskGrpSysId='$[jvar_sysid]'" class="container-fluid">


                           


                              <!-- Initialize wutad object -->


                           


                              <div data-ng-init="wutad='$[wutadString]'"></div>


                           


      <div class="row" data-ng-controller="TaskGroupActionsController">


                                      <div class="col-md-12">


                                                                                           


                                                                                              <table class="table table-striped">


                                                                                                                              <thead>


                                                                                                                                      <tr>


                                                                                                                                                                      <th class="center col-md-1">${gs.getMessage('Task?')}</th>


                                                                                                                                                                                              <th class="col-md-4">${gs.getMessage('Short Desc')}</th>


                                                                                                                                                                                              <th class="col-md-7">${gs.getMessage('Description')}</th>


                                                                                                                                                              </tr>


                                                                                                                              </thead>


                                                                                                                              <tr data-ng-repeat-start="action in wutActions">


                                                                                                                                                              <!-- 1 Task? -->


                                                                                                                                                              <td class="center col-md-1">


                                                                                                                                                                                              <span class="glyphicon"


                                                                                                                                                                                                          data-ng-class="


                                                                                                                                                                                                          {


                                                                                                                                                                                                                  'glyphicon-check': action.create_task === 'true',


                                                                                                                                                                                                                  'glyphicon-unchecked': action.create_task === 'false',


                                                                                                                                                                                                                  'hover': action['create_task'] == 'false' || action['create_task'] == 'true'


                                                                                                                                                                                                               


                                                                                                                                                                                                          }"


                                                                                                                                                                                                          data-ng-click="setUpTaskCreation($index);"


                                                                                                                                                                                                          aria-hidden="true">


                                                                                                                                                                                              </span>


                                                                                                                                                              </td>



                                                                                                                                                              <!-- 2 Action Short Desc -->


                                                                                                                                                              <td class="col-md-4">{{ action ['work_unit_type_action.short_description'] }}</td>


                                                                                                                                                              <!-- 3 Action Description -->


                                                                                                                                                              <td class="col-md-7">{{ action ['work_unit_type_action.description'] }}</td>


                                                                                                                              </tr>


                                                                                                                              <tr data-ng-repeat-end="">


                                                                                                                              </tr>


                                                                                              </table>


                                                              </div><!-- .col-md-12 -->


                              </div><!-- .row -->


</div><!-- .container-fluid -->


                                                           


<!-- UI Scripts are cached added this to force refreshing cache


      when a UI Script is updated.


      Main AngularJS scripts do not change so we don't need


      to reload them -->


<g2:evaluate var="jvar_stamp">


                              var gr = new GlideRecord('sys_ui_script');


                              gr.orderByDesc('sys_updated_on');


                              gr.setLimit(1);


                              gr.query();


                              gr.next();


                              gr.getValue('sys_updated_on');


</g2:evaluate>


                           


<g:requires name="angularjs.1.4.8.jsdbx" />


<g:requires name="angularjs.1.4.8.sanitize.jsdbx" />


<g:requires name="task_grp_actns_app.jsdbx" params="cache=$[jvar_stamp]" />


<g:requires name="task_grp_actns_controller.jsdbx" params="cache=$[jvar_stamp]" />


<g:requires name="task_grp_actns_factory.jsdbx" params="cache=$[jvar_stamp]" />



<!-- Style could be moved to content_css table -->


<!-- <link rel="stylesheet" href="content_css_record_sys_id.cssdbx"></link> -->


<style>


                              .center {


                                      text-align: center;


                              }


                           


                              .red {


                                      color: #d3232c;


                              }


                           


                              .white {


                                      color: white;


                              }



                              .hover {


                                      cursor: pointer;


                              }


                           


                              .gray {


                                      color:#a9a9a9;


                              }


                           


                              .narrative {


                                      font-weight: bold;


              font-size: 1.1em;


              margin: 0 8px 0 12px;


                              }


                           


                              i {


                                      font-size:.8em;


                                      padding-right:5px;


                              }


                           


                              div.process-step-container {


                                      margin-top:20px;


                              }


                           


</style>


                           


</j:jelly>


=========== END OF work_unit_type_actions_body MACRO ========================





Rgds,


Tor