- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 09-02-2019 05:16 AM
The problem.
When designing widgets, we often want to use a record watcher to notify us that the data we are monitoring has changed. To achieve this we would normally use spUtil like this
spUtil.recordWatch($scope, "<name of the table>", "<filter condition>", function(<parameters>) {
<your code here>
});
This works fine when we are only really interested in looking at one condition, but what happens when we want to change the filter condition? You know, when the user selects a different filter, how do we remove the old record watcher?
One option would be to reload the page to get rid of the old record watcher, but that is not great, we could use a variable to let the record watcher that we are now interested in is different and as such ignore the event. These are a little clunky and just mask the fact that we can't remove the record watcher we created using spUtil as we don't have a reference to the watcher any more.
The solution.
There is a way we can remove the old record watcher, but we have to create the record watchers in a different way. All spUtil is doing behind the scenes is calling snRecordWatcher which you can access directly.
Registering a record watcher (without spUtil)
Firstly add the snRecordWatcher as a parameter of the main client function, e.g.
function(spUtil,$scope,snRecordWatcher) {
/* widget controller */
var c = this;
}
Nowe we can add the following line will create a new recordwatcher and return it to the variable called tempWatch
var tempWatch = snRecordWatcher.initList('<table to filter>','<filter to apply');
This just registers the record watcher, next you need to specify the function you wish to execute. If you don't specify anything, the record watcher will simply execute the client main function()
So to register the function to execute, use the following
tempWatch.subscribe(function(<parameters>){
<Your code here to deal with the change>
});
Now store the "tempWatch" variable somewhere, e.g. c.data.tempWatch for example.
Un-subscribing a record watcher.
As I mentioned previously, now that you can store a reference to the record watcher, you can now execute the "unsubscribe" function which is available in the snRecordWatcher class
tempWatch.subsbscribe();
The record watcher will no longer fire on the filter condition that you applied and you can now re-register the record watcher for your new condition.
Worked Example.
In this example there is a simple table that is filtered using a drop down. I have not gone complicated with the filtering.
Client HTML
<div>
<div class="form-group">
<select class="form-control" id="filter1" ng_model="c.data.recordFilter" ng-change="c.filterChanged()">
<option></option>
<option>watch_me=false</option>
<option>watch_me=true</option>
</select>
</div>
<div class="list-group">
<a class="list_group_item" ng-repeat="data in c.data.record">
<div class="panel panel-primary">
<div class="panel-heading">
ID = [{{data.recordID}}]
</div>
<div class="panel-body">
Text = [{{data.text}}]
Number = [{{data.number}}]
</div>
</div>
</a>
</div>
</div>
Client Class
The client class has the function called by the drop down when a user selects a filter. if the record watcher has been applied, it is simply cleared and the new one added. The record watcher doesn't do anything fancy, simply calls the refresh of the data, but this is just an example. you can pass a variable into the watcher that contains the record that has been changes and just update your data accordingly, but for simplicity I have not done that here.
function(spUtil,$scope,snRecordWatcher) {
/* widget controller */
var c = this;
//Filter change function executed when user picks the filter they want to watch
c.filterChanged = function(){
spUtil.update($scope);
//if they previously picked a filter then unsubscribe the watcher
if (c.data.tempWatch) {
console.log('Attempting to unsubscribe the watcher');
c.data.tempWatch.unsubscribe();
}
//Create new snRecordWatcher and keep the object
var tempWatch = snRecordWatcher.initList('x_snc_record_watch_data',String(c.data.recordFilter));
c.data.tempWatch = tempWatch;
if (c.data.recordFilter == 'watch_me=false'){
//Add slightly different recordwatcher functions to show that it works.
console.log('[b] filter selected');
//subscribe the function to the recordwatcher, otherwise the main update is called
tempWatch.subscribe(function(data){
console.log('[b] record watcher');
spUtil.update($scope);
});
} else {
//As above but a different function to show a different message to the console.
console.log('[a] filter selected');
tempWatch.subscribe(function(){
console.log('[a] record watcher');
spUtil.update($scope);
});
}
}
}
Server Class
The server is just applying the filter and collecting the data to be shown on screen.
(function() {
/* populate the 'data' object */
/* e.g., data.table = $sp.getValue('table'); */
data.record = [];
var gr = new GlideRecord("x_snc_record_watch_data");
if (input){
gr.addQuery(input.recordFilter);
data.recordFilter = input.recordFilter;
}
gr.query();
while (gr.next()) {
data.record.push({
text: gr.getValue("watched_text"),
number: gr.getValue("watched_number"),
recordID: gr.getValue("number")
});
}
})();
Hopefully this was helpful, if it was please let me know in the comments.
- 1,763 Views

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks for this, was just wondering how to do this. You have one issue though. Above you say to call "tempWatch.subsbscribe();" and that did not work for me but using "tempWatch.unsubsbscribe();" did.