Reputation: 8380
I have a couple of forms that interact with a backend service to persist the data.
I am wondering if there's a standard angular way to detect what properties of the model has changed and send them only in the POST? Currently all is sent event when not changed.
Upvotes: 1
Views: 387
Reputation: 18435
As per the question, there can be two situations.
Once user has filled the fields and click on SAVE button which will finally send a PATCH request for saving//updating values.
As user changes the values, a request needs to be made.
For the 1.
You can keep a track of what's get changed by maintaining a hashmap. Use ng-modal
directive for all user input fields.
Let's assume there's two input fields i. username
and password
.
<input type="text" ng-modal="username" />
<input type="password" ng-modal="password" />
In your controller
$scope.userInfo = {
user: $scope.username,
pass: $scope.password
};
Now if anything gets changed, it will be reflected in your views and models via a two-way binding.
So, now you can compare the old and new values and accordingly send the desired ones.
For the 2.
Use Angular's watchCollection
.
scope.$watchCollection('[username, password]', function () {
// send a request
});
EDIT
One can use debounce method for the second approach
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
var timeout, args, context, timestamp, result;
var later = function() {
var last = _.now() - timestamp;
if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
if (!timeout) context = args = null;
}
}
};
return function() {
context = this;
args = arguments;
timestamp = _.now();
var callNow = immediate && !timeout;
if (!timeout) timeout = setTimeout(later, wait);
if (callNow) {
result = func.apply(context, args);
context = args = null;
}
return result;
};
};
Source: https://github.com/jashkenas/underscore/blob/master/underscore.js
Upvotes: 3
Reputation: 943
There is no standard way. This is one more approach sans watchers. You could pass 'form' as one the arguments on update and use the 'form' to identify which controls have become dirty.
http://plnkr.co/edit/8Og1m8eM54eOzKMDJtfJ?p=preview
.controller('ExampleController', ['$scope', function($scope) {
$scope.user = {}
var formFields = ['firstName', 'lastName'];
$scope.update = function(form, user) {
$scope.updatedFields = {};
angular.forEach(formFields, function(field) {
if (form[field].$dirty) {
$scope.updatedFields[field] = $scope.user[field];
//Temporarily set the field back to pristine.
//This is only for demo
form[field].$dirty = false;
}
});
};
}]);
You could use same string for input name and model.
<input type="text" ng-model="user.firstName" name="firstName"/>
Upvotes: 1