filype
filype

Reputation: 8380

How to send angular form data that has changed?

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

Answers (2)

softvar
softvar

Reputation: 18435

As per the question, there can be two situations.

  1. Once user has filled the fields and click on SAVE button which will finally send a PATCH request for saving//updating values.

  2. 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

Bharat
Bharat

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

Related Questions