A lot of the time when using record watch to show record updates in real-time I would just use the heavy handed approach of updating the whole scope with something akin to the following :
1 2 3 4 5 6 7 8 |
function($scope, spUtil) { var c = this; spUtil.recordWatch($scope, "incident", "active=true^state=3", function(name,data) { spUtil.update($scope); }); } |
This works well and gives the desired outcome, but in essence what is happening here is that even if just one record in a list has changed then the whole list is refreshed. What if we wanted to have a lighter touch on things and perhaps add some animations like so:
Note – Open the video in full screen for best results – The animation is not as smooth as I would like in the video, but trust me, in real life it’s breathtaking. 🙂
So how did I achieve this? Firstly I used a handy library for cross browser css animations called animate.css and also dug a little bit deeper into the record watch tool. Lets take a look at the widget.
Widget
HTML:
Note – I have put the link to animate.css in the html of the widget for ease of this example, normally it would be linked to in the theme.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css"> <div ng-if="data.incidents.length > 0" class="panel panel-{{::options.color}} b"> <div class="panel-heading"> <h4 class="panel-title">{{options.title}}</h4> </div> <div class="panel-body"> <ul id="list"> <li ng-repeat="a in data.incidents" id="{{::a.number}}">{{::a.number}}</li> </ul> </div> </div> |
CSS:
1 2 3 4 5 6 7 8 9 10 11 12 |
#list li { list-style: none; background: #d1703c; border-bottom: 2px solid #fff; color: #fff; padding: 0 0.5em; margin: 0; height: 2em; overflow: hidden; line-height: 2em; width: 10em; } |
Server Script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
(function() { //get all the incidents that have a state of "On Hold" (3) var onHoldIncs = new GlideRecord('incident'); onHoldIncs.addEncodedQuery('active=true^state=3'); onHoldIncs.query(); //create an empty array to hold these incidents data.incidents = []; //loop through the result set while (onHoldIncs.next()) { //create an empty object var a = {}; //add the incident's number to an attribute on our new object a.number = onHoldIncs.getValue('number'); //push the object into the array data.incidents.push(a); } })(); |
Client Script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
function($scope, spUtil) { var c = this; //create the record watch ensuring we are targeting the same table with the same condition as the server script. spUtil.recordWatch($scope, "incident", "active=true^state=3", function(name,data) { //check if the action that occured was "entry" i.e. an new record coming into the record set if(data.action == "entry"){ //use some "nasty" DOM manipulation to get the list element var list = document.getElementById('list'); //create a new list item element var newLI = document.createElement('li'); //put the new incidents number in the inner HTML newLI.innerHTML = data.display_value; //give the new elements id a value of the new incidents number so we can identify it later if needed newLI.id = data.display_value; //insert the new element into the top of the list list.insertBefore(newLI, list.firstChild); //set a short timeout before applying the animate.css class so the element exists before we animate it's entrance setTimeout(function() { newLI.className = newLI.className + " animated fadeInLeftBig"; }, 10); } //check if the action that occurred was "exit" i.e. a record leaving the record set else if(data.action=="exit"){ //set id equal to the old incidents number var id = data.display_value; //get the element with the id of the old incident var oldLI = document.getElementById(id); //apply the animate.css class to the element to animate it's exit oldLI.className = oldLI.className + " animated hinge"; //set a slightly longer timeout to allow the animation to end before we remove the element from the DOM completely setTimeout(function() { oldLI.parentNode.removeChild(oldLI); }, 3000); } }); } |
Note – Don’t forget to pass $scope and spUtil into your function.
It is the two objects (name and data) that are passed into the record watch function that allow us to interrogate not only the event that has occurred but the data that has changed during that event. The best way to see what is available to you is to log these two objects to the console and play around:
1 2 3 4 5 6 7 8 9 |
function(spUtil, $scope) { /* widget controller */ var c = this; spUtil.recordWatch($scope, "incident", "active=true^state=3", function(name, data) { console.log(name); //Returns information about the event that has occurred console.log(data); //Returns the data inserted or updated on the table }); } |
This post was merely meant as a quick example to show how we can use record watch with more precision than just blindly refreshing the whole scope. I doubt my example has a place in the real world but hopefully it has helped someone or at least piqued someones interest to go digging into record watch further themselves.