- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-05-2020 07:05 AM
Hello all,
I am new to Service Portal, creating my very first sample widget today. I have this piece of code below where after clicking "Edit'" button and then clicking on "Save" button, the record should get updated in the incident table. I am able to make changes after clicking "Edit" button, but I am stuck w.r.to updating the changes upon clicking "Save" button. Could you please help me on this.
Serverside:
(function() {
data.incidentdata=[];
var gr=new GlideRecord('incident');
gr.addEncodedQuery('state=2');
gr.query();
while(gr.next())
{
var dataobject={};
dataobject.priority=gr.getDisplayValue('priority');
dataobject.short_description=gr.getDisplayValue('short_description');
dataobject.state=gr.getDisplayValue('priority');
data.incidentdata.push(dataobject);
}
})();
Clientside:
function($scope) {
var c = this;
$scope.display=true;
$scope.saveRecord=function () {
}
}
HTML:
<div>
<p ng-repeat='incident in data.incidentdata'>
<span ng-if='display'>{{incident.short_description}}</span>
<input type='text' ng-model='incident.short_description' ng-if='!display'/>
<button ng-click='display=false'>Edit</button>
<button ng-if='!display' ng-click='saveRecord()'>Save</button>
</p>
</div>
Moreover, I've one more question. How can we use this controller "c" in client script? What is the difference between initializing variables/functions with "$scope" and "c". I did go through a few articles on these, but it will be really helpful if you can explain with an example.
Thank you.
Solved! Go to Solution.
- Labels:
-
Service Portal Development
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-08-2020 11:52 AM
Hi Vinay,
To clear up when to use $scope or c or the difference between $scope or c:
AngularJs inherently has a $scope upon creating/define the ng-app. Each controller has their own scope, just like a function.
A directive (which is what Service Portal's widgets are) has access to scope and can have its own isolated scope. This is what ServiceNow has setup for Service Portal widgets (isolated scopes) so that each widget can have multiple instances on the same page.
But when you want access to the parent scope you need to inject that into the controller.
ie. function($scope) { ....
"c" in the widget is the same as a normal "this" in a function.
The HTML template is the view and it has access to the inherent $scope. So theoretically you can create and assign values in the HTML template.
If something like this is in the HTML template:
<input type="text" ng-model="myvar" ng-init="myvar ='hello'" />
You wouldn't be able to access it in the controller unless you injected $scope and called $scope.myvar
So instead of initializing the variable value in the view the better way to do it would be to first set it in the controller which can be done in a couple of ways:
Controller:
function($scope) {
...
$scope.myvar = 'hello';
...
<input type="text" ng-model="myvar" />
Notice the ng-init doesn't have to be used
The other way is to use c
Controller:
function(){
...
var c = this;
c.myvar = 'hello';
...
HTML:
<input type="text" ng-model="c.myvar" />
Notice $scope doesn't have to be injected.
However, both of these can exist together but they are two totally different objects and you would have to access them respectively to their "scope".
None of this has anything really to do with updating the actual database value if the value is coming from records.
In the previous posts, everyone is trying to tell you that the function "$scope.saveRecord" isn't doing anything.
The function would need to send that data back to the server script and then have logic to actually update the desired record.
An example:
Server Script:
(function(){
if(input){
var gr = new GlideRecord('incident');
gr.get(input.sys_id);
if(gr.getUniqueValue()){
gr.short_description = input.short_description;
gr.update();
}
}
})()
In the gif below you'll see an example of using some "update" functions that do different things.
You can see here that it doesn't necessarily matter whether you use $scope.server.update or c.server.update (there is also ".server.get" that allows you to add items to 'input').
But it does matter knowing how to update the variables' values properly. Another thing to know is that server.update/get has a .then/promise where you can refresh/update the view if necessary. That is where using data directly in the HTML template can come in handy. If the logic allows to limit to manipulating the properties on data, these would automatically get updated once data is updated if one-way binding isn't enforced.
Attached is the widget I created. Play around with it.
I hope this helps and didn't confuse you more.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-05-2020 10:15 AM
Hi,
So my code should work. Only thing you need to out in that code is the glideRecord method in if condition which i have mentioned. I though miss on thing that where are you storing the Sysid of the record been edited?
What happens when you click on edit button?
Thanks,
Ashutosh
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-05-2020 10:54 AM
After clicking on "edit" button, as per the code, it's allowing me to edit, but when I click on "Save", nothing is happening. I had the same question about how to store sys id. I'm actually confused between when to use $scope, and c. I have seen people using "c" in the ng-model as well in the HTML. Not sure how that works either.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-05-2020 07:45 AM
Hi vinay
missing the gr.update(); //method
-------------------------------------------------------------------
How can we use this controller "c" in client script?
Ans:
to send data from Client controller to Server side
Normally these two methods on "this" or "c "are used:
- .server.update() - Automatically sends this.data to the server as input
- .server.get() - Sends a custom input object
folowing simple example to understand the client and server communication through "c":
Client Script:
function($scope) {
var c = this;
c.data.abc='Any Name'; //sending the value
c.update = function() {
c.server.update().then(function (response) {
c.data = {};
})
}
}
Server side you can use
if(input) //input is server side object used when receiving the data.
{
gs.addInfoMessage("input.abc");
}
If it help mark helpful or correct
Thanks and regards
Anil
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-06-2020 11:32 AM
Can anyone please help me on this. The issue still persists!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-08-2020 11:52 AM
Hi Vinay,
To clear up when to use $scope or c or the difference between $scope or c:
AngularJs inherently has a $scope upon creating/define the ng-app. Each controller has their own scope, just like a function.
A directive (which is what Service Portal's widgets are) has access to scope and can have its own isolated scope. This is what ServiceNow has setup for Service Portal widgets (isolated scopes) so that each widget can have multiple instances on the same page.
But when you want access to the parent scope you need to inject that into the controller.
ie. function($scope) { ....
"c" in the widget is the same as a normal "this" in a function.
The HTML template is the view and it has access to the inherent $scope. So theoretically you can create and assign values in the HTML template.
If something like this is in the HTML template:
<input type="text" ng-model="myvar" ng-init="myvar ='hello'" />
You wouldn't be able to access it in the controller unless you injected $scope and called $scope.myvar
So instead of initializing the variable value in the view the better way to do it would be to first set it in the controller which can be done in a couple of ways:
Controller:
function($scope) {
...
$scope.myvar = 'hello';
...
<input type="text" ng-model="myvar" />
Notice the ng-init doesn't have to be used
The other way is to use c
Controller:
function(){
...
var c = this;
c.myvar = 'hello';
...
HTML:
<input type="text" ng-model="c.myvar" />
Notice $scope doesn't have to be injected.
However, both of these can exist together but they are two totally different objects and you would have to access them respectively to their "scope".
None of this has anything really to do with updating the actual database value if the value is coming from records.
In the previous posts, everyone is trying to tell you that the function "$scope.saveRecord" isn't doing anything.
The function would need to send that data back to the server script and then have logic to actually update the desired record.
An example:
Server Script:
(function(){
if(input){
var gr = new GlideRecord('incident');
gr.get(input.sys_id);
if(gr.getUniqueValue()){
gr.short_description = input.short_description;
gr.update();
}
}
})()
In the gif below you'll see an example of using some "update" functions that do different things.
You can see here that it doesn't necessarily matter whether you use $scope.server.update or c.server.update (there is also ".server.get" that allows you to add items to 'input').
But it does matter knowing how to update the variables' values properly. Another thing to know is that server.update/get has a .then/promise where you can refresh/update the view if necessary. That is where using data directly in the HTML template can come in handy. If the logic allows to limit to manipulating the properties on data, these would automatically get updated once data is updated if one-way binding isn't enforced.
Attached is the widget I created. Play around with it.
I hope this helps and didn't confuse you more.