Watch List Service Portal Help

Chaz
Tera Guru

Hello Community!

I am working on a Service Portal widget to allow users to add to the watch list. I used the code from the widget provided in the ServiceNow Elite blog.

https://www.servicenowelite.com/blog/2017/6/1/service-portal-watchlist-widget?rq=watch%20list

I took the code from both widgets and blended them together so that users can select someone from the list or add an email address manually. The code works fine for manual entries. The problem I'm running into is if you select someone from the users list and the manual box is blank it sets an "undefined" value as well. I'm not the greatest at widget scripting and was wondering if anyone could spot my issue?

Widget Screenshot

find_real_file.png

 

HTML

<div class="panel panel-default" ng-if="data.canRead">  
	<div class="panel-heading">       
    <h4 class="panel-title pull-left" style="font-size: 14px;" ng-click="c.variable_toggle = !c.variable_toggle" aria-expanded="{{c.variable_toggle}}" aria-controls="variables-toggle">       
     <span style="font-size: 12px;" class="glyphicon" ng-class="c.variable_toggle ? 'glyphicon-chevron-down' : 'glyphicon-chevron-up'"></span> ${Watch List Actions}
    </h4>   
    <div class="clearfix"></div>       
  </div>   
  <div ng-if="c.variable_toggle"class="panel-subheading" align="center" style="font-size: 12px;">${Click in the white box below to add users and select the "Update" button}</div>
  <div ng-if="c.variable_toggle"class="panel-body">
    <form ng-click="save()">
      <div class="text-center text-italic text-muted">
        <div>
          <sn-record-picker field="watch_list" sn-disabled="!data.canWrite" table="'sys_user'" display-fields="'name'" display-field="'email'" search-fields="'name'" value-field="'sys_id'" default-query="'active=true^web_service_access_only=false^user_nameISNOTEMPTY^emailISNOTEMPTY'" page-size="10" multiple="true"></sn-record-picker>   </div>
        <div style="margin-top:15px; float: right;">
          <button ng-if="data.canWrite" type="submit" class="btn btn-primary btn-sm">${Update}</button>
        </div>
      </div>
    </form>
  </div>
  
  <div ng-if="c.variable_toggle" class="panel-body" style="font-size: 12px;">
<form>
${Distribution lists: type an email address in the box below and select the "Update" button}
<div class="textbox_space">
<input ng-disabled="!data.canWrite" ng-model="data.watch_list" id="watch_list_dist" class="form-control" type="email" maxlength="50" />
</div>
<input ng-if="data.canWrite" ng-click="save()" type="submit" id="submit" value="Update" class="btn btn-primary btn-sm" style="margin-top:10px; float: right;"/>
</form>
  </div>

 

Client Script

function($scope, spUtil, $http) {   
	var c = this;   

	$scope.watch_list = {   
		displayValue: c.data.displayValue,   
		value: c.data.value,   
		name: 'watch_list'
	};   
	$scope.save = function(){   
		c.data.watchList = $scope.watch_list.value;   
		c.server.update().then(function()   {
		
	spUtil.recordWatch($scope, c.data.table, "sys_id=" + c.data.sys_id, function(name, data) {   
		if(name.name == 'record.updated' && data.operation == 'update'){   
			$scope.watch_list.value = data.record.watch_list.value;   
			$scope.watch_list.displayValue = data.record.watch_list.display_value;   
			$scope.$apply();   
		} 
	});   
	});
	$scope.$on("field.change", function(evt, parms) {
		if (parms.field.name == 'watch_list'){}
		
		});
	};
}

 

Server Script

(function() {   
	var gr;
//if the user inputs data
	if(input){   
		gr = new GlideRecord(input.table);   
		if(gr.get(input.sys_id)){   
	// if user has write access allow update of list
			if(gr.watch_list.canWrite()){   
				gr.watch_list = input.watchList;   
				gr.update();   
				gs.addInfoMessage('Watch List Updated');   
			}   
	//if user does not have write access show error message
			else{   
				gs.addErrorMessage("Update failed, you don't have the required access");   
			}   
		}   
	}   
	//if user isn't inputting data
	else{   
		var table = $sp.getParameter('table');   
		var sys_id = $sp.getParameter('sys_id');   
		gr = new GlideRecord(table);
	//Get the record data
		if(gr.get(sys_id)){   
			data.table = table;   
			data.sys_id = sys_id;   
			data.canRead = gr.watch_list.canRead();   
			data.canWrite = gr.watch_list.canWrite();   
	//if user has read rights, display the watch list values
			if(data.canRead){   
				var dV = gr.getDisplayValue('watch_list');   
				var sV = gr.getValue('watch_list');   
				//data.displayValue = dV == '' ? [] : dV;   
				//data.value = sV == null ? [] : sV;   
				data.displayValue = dV;
				data.value = sV;
			}   
		}   
	}   
	
})();
	
	/*distribution list function*/
(function() {
data.sys_id = $sp.getParameter('sys_id');
//if the user inputs data find the record
if (input) {
data.sys_id = input.sys_id;
var grTask = GlideRecord("task");
grTask.query("sys_id", data.sys_id);
grTask.query();

if (grTask.next()) {
var wList = grTask.watch_list;
var wEmail = input.watch_list;
// If there's already users listed
if(wList != "") {
wList = (wList + "," + wEmail);
}
//If the watch list is empty
else {
wList = wEmail;
}
//Update the record with new Watch List values
grTask.watch_list = wList;
data.displayValue = wEmail;
grTask.update();
}
}
})();

	

 

Any help is greatly appreciated!

1 ACCEPTED SOLUTION

Mike Patel
Tera Sage

Try below server script

(function() {
	var gr;
	//if the user inputs data
	if(input){
		gr = new GlideRecord(input.table);
		if(gr.get(input.sys_id)){
			// if user has write access allow update of list
			if(gr.watch_list.canWrite()){
				gr.watch_list = input.watchList;
				gr.update();
				gs.addInfoMessage('Watch List Updated');
			}
			//if user does not have write access show error message
			else{
				gs.addErrorMessage("Update failed, you don't have the required access");
			}
		}
	}
	//if user isn't inputting data
	else{
		var table = $sp.getParameter('table');
		var sys_id = $sp.getParameter('sys_id');
		gr = new GlideRecord(table);
		//Get the record data
		if(gr.get(sys_id)){
			data.table = table;
			data.sys_id = sys_id;
			data.canRead = gr.watch_list.canRead();
			data.canWrite = gr.watch_list.canWrite();
			//if user has read rights, display the watch list values
			if(data.canRead){
				var dV = gr.getDisplayValue('watch_list');
				var sV = gr.getValue('watch_list');
				//data.displayValue = dV == '' ? [] : dV;
				//data.value = sV == null ? [] : sV;
				data.displayValue = dV;
				data.value = sV;
			}
		}
	}

})();

/*distribution list function*/
(function() {
	data.sys_id = $sp.getParameter('sys_id');
	//if the user inputs data find the record
	if (input) {
		if(input.watch_list){
			data.sys_id = input.sys_id;
			var grTask = GlideRecord("task");
			grTask.query("sys_id", data.sys_id);
			grTask.query();

			if (grTask.next()) {
				var wList = grTask.watch_list;
				var wEmail = input.watch_list;
				// If there's already users listed
				if(wList != "") {
					wList = (wList + "," + wEmail);
				}
				//If the watch list is empty
				else {
					wList = wEmail;
				}
				//Update the record with new Watch List values
				grTask.watch_list = wList;
				data.displayValue = wEmail;
				grTask.update();
			}
		}
	}
})();

View solution in original post

19 REPLIES 19

GoBucks
Mega Sage

@ChazI have created a widget using your code above (HTML, Client script, and Mike Patel's corrected Server script he provided you above). I simply copied the all the code.  I've created this widget on a PDI.  However, I must not have something correct because the widget does nothing for me.  I have placed it at the bottom of the Standard Ticket page.  Is all that server script for one widget?  I ask because I see 2 functions.

 

And, if the record already contains users or emails in the watch list, do these widgets reflect that?  Or, are they always empty fields onload of the page? (ie, they're just for ADDING to what might already be in the watch list).

 

Just trying to get this to work...

Hello @GoBucks ,

It's been a long time since I've seen this widget but I placed it in my PDI to check it out and it looks like it still works as expected. Can you verify the widget was properly added to the portal page? If you're adding it to the Standard Ticket page you'll need to be sure you're in the "Service Portal - Standard Ticket" scope to have it accept your changes.

To answer your questions, yes, the widget reflects all current watchlist assignments so if a person is added on the platform side the user will be visible in the list on the portal side. So this means that via either view the list of users will be visible and editable.

Chaz_0-1673973092535.png

Chaz_1-1673973112334.png

 

@Chaz- thanks for the feedback.  I went ahead and recorded a 10 min video of me walking through creating this widget and trying to implement it.  I point out some of the issues I'm seeing.

 

https://oh-tech.webex.com/oh-tech/ldr.php?RCID=9fc3e6a0a50f823eb6412876627c7d50

 

@Mike Patel- in case you could be of help as well since you provided Chaz some help on this post.

 

Thanks for any help,

Jeff

Hi @GoBucks , thanks for the video. It was really helpful! 

First, the client script is a bit dated but should still be functional with the new standards. You may add the api.controller= in front of the function to accommodate the new configurations with ServiceNow but should not break anything otherwise.

 

Second, there is a recordwatcher within the client script that should update the widget when the form is updated on the platform side. You'll see that with this bit of code below

spUtil.recordWatch($scope, c.data.table, "sys_id=" + c.data.sys_id, function(name, data) {  
				if(name.name == 'record.updated' && data.operation == 'update'){   
					$scope.watch_list.value = data.record.watch_list.value;   
					$scope.watch_list.displayValue = data.record.watch_list.display_value;   
					$scope.$apply();   
				} 
			});   


For the error message you are receiving. It looks like an object in the input might not be getting applied. Try replacing line 51 with the following code:

data.table = input.table;
var grTask = GlideRecord(data.table);

 

If that doesn't work, try applying console.log(input) on the line above to see what data is actually coming across. Example below:

Chaz_0-1674156435269.png

 

@Chaz- Thanks for the continued assistance!

 

My reply I just typed seems to have not gotten posted 🤔

 

In short, I have only copied/pasted what was provided in your post (with Mike's correction to the server-side script).  So, I have no idea why the widget data is not live updating when I update the same record in the platform.

 

Regarding the client script, the IF block in this snippet of code is empty.  So, what exactly is this doing?

$scope.$on("field.change", function(evt, parms) {
if (parms.field.name == 'watch_list') {}
});

 

And just to clarify, this is a single widget with TWO self-invoked functions within its server script?

 

I tried editing line 51 with what you provided, but got same results as I had been (as seen in video).

 

Finally, with console.log I tried adding an email address string and clicking update.  Here was the output.  You can see the email string here.  It is obviously not getting updated on the record though.

 

GoBucks_1-1674248290685.png

aa