service portal widget to update a record

raycallan
Giga Guru

Hi Community,

I have a requirement to add a widget to the service portal to allow a user to escalate an incident. This is my fist time working with widgets so I have difficulty passing values between the html template and the server script

if it is not already escalated

  • They will select a escalate reason from an sn-record-picker
  • Enter their comment in a multiline textarea
  • Submit their comments which will update the incident record

if it is escalated

  • hide the widget

3 issues i have

  1. I'm unable to get the html template to get the value of the u_escalated filed (true/false). it always sees a 'false' value (log shows [object Object])
  2. I'm unable to get the the value of the sn-record-picker, (log shows 'undefined' value')
  3. My recording is not updating (not getting to gr.update)

Here is screen caps of my code

Escalate_html.PNG

Escalate_server.PNGEscalate_client.PNG

This is the log

Escalate_log.PNG

Thanks Ray

11 REPLIES 11

gustavogarcia_n
ServiceNow Employee
ServiceNow Employee

Hi Ray,



Regarding your first question, I reviewed the $sp.getField listing in the github developer documentation and found the following:


Returns {display_value, label, type, value} for a given field on a GlideRecord.



This would explain why you get an object value. Either set escalated to the value in your server script or pick the value field from escalated in the HTML template.



Thanks,Gustavo Garcia


raycallan
Giga Guru

Hi Community,



I have eventually got this working almost!!



For issue 1 - as Gustavo pointed out, I needed to reference the value (ng-if="data.escalated.value === '0'")


For issue 2 - I was stiil unable to get the value of the record picker when the Escalate Button was clicked   .


        My workaround was to add a hidden field to store the selected value of the record picker. I then reference this hidden field when the Escalate Button is clicked


For issue 3 - I re-copied the code from Nathan Firth's article - https://serviceportal.io/create-custom-action-buttons-service-portal/ and it worked



The only issue I have is that when I change the value of the record picker the parms.field.name returns undefined.   I can bypass this as this is the only field change on this widget but I would like to get it to work properly before going live



$scope.$on("field.change", function(evt, parms) {


  confirm(parms.field.name + ' ' + parms.newValue + ' ' +parms.displayValue);


  //if (parms.field.name == 'reason_picker'){


  c.data.reason = parms.newValue;


  //}


  });



For anyone who is interested in this here is my full code



html script


<div class="panel b">


  <div class="panel-heading bg-primary">


      <h4 class="panel-title pull-left">


          ${Escalation}


      </h4>


      <div class="clearfix"></div>


  </div>




  <div class="panel-body">


      <div ng-if="data.escalated.value === '0'">


          <div class="row pull-left">


              ${If you feel your ticket is not being responded to in an appropriate manner, please complete the form below to escalate}


          </div>


          <div class="row">


              <label>${Escalate Reason}</label>


              <sn-record-picker field="reason_picker" table="'sys_choice'" placeholder="${Select a resaon}"


                                                  display-field="'label'" value-field="'value'"


                                                  default-query="'element=u_escalate_reason'"></sn-record-picker>


              <input class="form-control" ng-model="c.data.reason" type="hidden" />


          </div>


          <div class="row">


              <label>${Escalate Comments}</label>  


              <textarea class="form-control" ng-model="c.data.comments"></textarea>        


          </div>


          <div class="clearfix"></div>


          <div class="row">


              <button type="button" class="btn btn-primary btn-block" ng-click="c.uiAction('escalate')">${Escalate Incident}</button>


          </div>


      </div>


      <div ng-if="data.escalated.value === '1'">


          <div class="row pull-left">


          ${This ticket has already been escalated!}


          </div>


          <div class="row">


              <div class="col-md-12 col-sm-12 col-xs-6 m-b break-word" ng-repeat="field in data.fields"


                        ng-if="field.value && (field.type != 'decimal' || field.type == 'decimal' && field.value != 0)" >


                  <label class="m-n">{{field.label}}</label>


                  <span ng-switch="field.type">


                      <div ng-switch-when="glide_date_time" title="{{field.display_value}}">


                          <sn-time-ago timestamp="::field.value" />


                      </div>


                      <div ng-switch-default >{{field.display_value}}</div>


                  </span>


              </div>


          </div>


      </div>


  </div>


 


</div>



Client Script


function ($scope, spUtil) {



  var c = this;



  $scope.$on('record.updated', function(name, data) {


  spUtil.update($scope);


  });



  $scope.$on("field.change", function(evt, parms) {


  confirm(parms.field.name + ' ' + parms.newValue + ' ' + parms.displayValue);


  //if (parms.field.name == 'reason_picker'){


  c.data.reason = parms.newValue;


  //}


  });



  c.uiAction = function(action) {


  if(c.data.comments == undefined || c.data.reason == '') {


  (alert("Please ensure you have selected a reason and entered comments"));


  return;


  }


  if(!confirm("Are you sure you wish to escalate?"))


  return;


  c.data.action = action;


  c.server.update().then(function() {


  c.data.action = undefined;


  })


  }


}



Server Script


(function(){


  var rec = $sp.getRecord();


  if (rec == null){


  return;


  }



  var escalated = $sp.getField(rec, 'u_escalated');


  var fields = $sp.getFields(rec, 'u_escalate_reason,u_escalate_comments');



  data.escalated = escalated;


  data.fields = fields;



  data.table = input.table || $sp.getParameter("table")|| options.table;


  data.sys_id = input.sys_id || $sp.getParameter("sys_id") || options.sys_id;



  // Valid GlideRecord


  var gr = new GlideRecord(data.table);


  if (!gr.isValid())


  return;



  // Valid sys_id


  if (!gr.get(data.sys_id))


  return;



  if (input) {


  var action = input.action;


  // If Incident table


  if (data.table == 'incident') {


  if (action == 'escalate') {


  // Escalate Incident


  gr.setValue('u_escalate_reason', input.reason);


  gr.setValue('u_escalate_comments', input.comments);


  gr.setValue('u_escalated', true);


  gr.setValue('escalated_by', gs.getUserID());


  gr.setValue('comments', 'incident escalated');


  gr.update();


  }


  }


  }


})();



Here is the outputs


Before EscalationAfter Escalation
Escalate.pngEscalated.png

Hi Ray,



You missed to copy paste the html template. Can you share, thank you.


Hello Ray,

Thanks for this post. It works like charm.

My issue is Escalate Comments is not updating in Incident form.