Published at:
3.9.17
AngularJS is awesome! Yeah, it is, even after so many competitors it still did not lose its value and manages to be on top of others. So we all love it and wonder how it can be so cool, same goes for me. The one thing I really inspired with is Angular's
Before starting this tutorial I would like to inform you that this is not about how Angular's watch function works neither I am saying that this is how Angular
So the story starts with
Now as we know we can attach properties to any JS object but do you know in how many ways we can attach them?
1#
2#
These two ways are very common and most used but there is another unconventional way which is
so if we use
If property already attached with object then
Now we need watch function as a property of our
but we can change watch value any time intentionally or accidentally ☹ like this
But with
watch
function which automatically gets called when object bind with $scope
got changed. So it's inevitable for me to learn how watch function works and by learning this I come up with the idea that how I can create my own simple watch function with simple JavaScript.Before starting this tutorial I would like to inform you that this is not about how Angular's watch function works neither I am saying that this is how Angular
watch
works. There are many web articles present on this topic and you can easily find them using Google. Instead of it, this post focuses on how we can create our own function which acts like Angular's watch function up to some extent!So the story starts with
JavaScript Objects
. Let's create onevar obj = {};
Now as we know we can attach properties to any JS object but do you know in how many ways we can attach them?
1#
obj.a = 1;
2#
obj['b'] = 2;
These two ways are very common and most used but there is another unconventional way which is
Object.defineProperty
. So it works like thisObject.defineProperty(object, propertyToBeAttached, configuration)
so if we use
Object.defineProperty
we add a property like thisObject.defineProperty(obj, 'c', { value: 3 });
If property already attached with object then
Object.defineProperty
also use to modify its configuration but why go for this complicated method when we can simply create property with [.] notation?Object.defineProperty
provides many extra options to control properties of object, you can read about it on MDN [please read it first if you don't know about it]. But real fun starts with set
and get
methods for property provided by Object.defineProperty
. TLDR version of these methods is get
method invokes automatically
every time when you try to access property's value and set
method invokes when you try to set value of property. And yes you get it right we need these methods of property being watched by our watch function so hold this in your mind.Now let's begin
First of all, we need$scope
so let's initialize itvar $scope = {};
Now we need watch function as a property of our
$scope
object and Angular's watch function takes two mandatory arguments first one is property to be watched another one is handler function and handler gives us the new and old value of the property. At first its very easy to attach watch function with $scope
var $scope = {};
$scope.watch = function (propToWatch, handler) {};
but we can change watch value any time intentionally or accidentally ☹ like this
var $scope = {};
$scope.watch = function (propToWatch, handler) {};
$scope.watch = 1;
But with
Object.defineProperty
we can also lock properties so why shouldn't we do itvar $scope = {};
Object.defineProperty($scope, 'watch', {
value: function (varToWatch, handler) {},
writeable: false,
configurable: false
});
Now as we have a property which we are going to watch so next step is we need its
set
and get
methods so let's use Object.defineProperty
to modify varToWatch
and add set
and get
methodsvar $scope = {};
Object.defineProperty($scope, 'watch', {
value: function (varToWatch, handler) {
Object.defineProperty($scope, varToWatch, {
set: function (newValue) {},
get: function () {}
});
},
writeable: false,
configurable: false
});
As I mentioned earlier
set
is going to call every time we set the value of the property so this is the point when we will invoke our handler functionvar $scope = {};
Object.defineProperty($scope, 'watch', {
value: function (varToWatch, handler) {
Object.defineProperty($scope, varToWatch, {
set: function (newValue) {
handler(newValue);
},
get: function () {}
});
},
writeable: false,
configurable: false
});
But now what about old value? Its easy and this is final steps and our watch function is ready ;)
var $scope = {};
Object.defineProperty($scope, 'watch', {
value: function (varToWatch, handler) {
var oldValue = $scope[varToWatch];
Object.defineProperty($scope, varToWatch, {
set: function (newValue) {
handler(newValue, oldValue);
oldValue = newValue;
},
get: function () {
return oldValue;
}
});
},
writeable: false,
configurable: false
});
Here we are caching property value from
$scope
in an oldValue
variable and we don't care about if it's already defined or not as it will set undefined
if the property is not set yet! Here you go we have created our very own simple watch function which really works we can use it just like we Angular's watch$scope.a = 1;
$scope.watch('a', function (newValue, oldValue) {
console.log(newValue, oldValue);
});
That's all folk you can play with it here
Thanks for ready! Your comments are welcome and happy coding!
Informative !! highly appreciable :)
ReplyDeleteHelpful.... Thanks :)
ReplyDelete