-
Notifications
You must be signed in to change notification settings - Fork 28
Observe
As the internal mechanism, Asta4js implements the 2-way binding by a built-in observing mechanism which can be used directly by developers too.
Basically, all the javascript model/variable can be observed, array can be observed as well.
-
_on_change
As mentioned in the Basic Usage, we performed rendering/binding by a snippet which is created by scope's snippet method, for simple observing, the snippet is not necessary, then it becomes simpler:
$scope.data = {}; $scope.observeData = {}; $scope.observe($scope.data, { value: { _on_change: function(newValue, oldValue){ $scope.observeData.value = newValue + "-observed"; } } }
The given meta can be a function which will be treated as "_on_change" by default:
$scope.observe($scope.data, { value: function(newValue, oldValue){ $scope.observeData.value = newValue + "-observed"; } }
-
_register_assign
It would be rarely to be used but as the way how the Asta4js bind the DOM's value change to model/variable, the "_register_assign" can be directly used by developers too.
$scope.observe($scope.data, { value: { _register_assign: function(bindContext, changeHandler){ // register some event monitor the handle the external changes, and the given changeHandler can be called to do the real assignment. var target = $("#someinput"); target.change(function(){ changeHandler(target.val(), bindContext); }); // we have to return a function which can be use to perform force assignment return function(){ changeHandler(target.val(), bindContext); }; } } }
As the matter of fact, the above example is the default inner implementation of framework for monitoring input changes.
Things become a little bit complicated for observing an array. Basically, we will want to observe 3 types of change event on an array reference: array reference change, array splice, array item change.
To achieve the various observing tasks on array, the following meta format can be used:
$scope.observe($scope.data, {
list:
{
_splice: {
_on_change: function(splices){
splice.index; // index position that the change occurred.
splice.removed; // an array of values representing the sequence of elements which were removed
splice.addedCount; // the number of elements which were inserted.
}
},
_value : {
_on_change: function(newValue, oldValue, bindContext){
var index = bindContext._getArrayIndex(); // the index of current item's last dimension
var indexes = bindContext._getArrayIndexes(); // the all indexes of the current item's all dimensions
}
},
_item : {
_value: {
_on_change: function(newValue, oldValue, bindContext){
// common value observing
}
}
}
}
});
(See the real usage age of array observing at todoApp)
The above example the raw format of array observing, which is obviously difficult to use for common array observing tasks(usually we will want to map the observing target array to a new array), thus we can use the following format to make things easier:
$scope.observe($scope.data, {
list: {
_array_map: function(newValue, oldValue, bindContext){
var list = $scope.observeData.list;
var hopeLength = Array.isArray(newValue) ? newValue.length : 0;
Aj.util.arrayLengthAdjust(list, hopeLength, function(){//initialize new item
return "";
}, function(item, index){//discard mapped items
//if necessary, this is a chance to clear the resource of mapped item before they are removed
//item.discard()
});
return list;
},
_array_discard: function(bindContext){
delete $scope.observeData.list;
},
_item: {
_value: function(newValue, oldValue, bindContext){
// via index
var targetIndex = bindContext._getArrayIndex();
$scope.observeData.list[targetIndex] = $scope.data.list[targetIndex] + "-observed-changed";
}
}
}
});
The "_array_map" will be called on array reference change and splice both, so the developer have the chance to return a mapped array for the given changed target array. "Aj.util.arrayLengthAdjust" is a help functioni to helper developers adjust the length of mapped array simply, of course, you can do your own mapping logic without this function.
"_array_discard" will be called when current bind context is dicarded, bascially just release the mapped array's memory is enough.
"_item" is the as the same as what has been mentioned in rendering/binding, to handle the item change. the "_value" means we want to handle the change of item itself rather it's proerties.
If we do not assign the value to the item itself but assign to the item's properies, "_mappedItem" of bind context can be used to make things simpler:
$scope.observe($scope.data, {
list: {
...
_item: {
_value: function(newValue, oldValue, bindContext){
//the magic age should be 10 years younger than the real age
bindContext._mappedItem.magicAge = newValue - 10;
}
}
}
});