Can you have a custom trigger for updating ng-model fields in Angular?

All we need is an easy explanation of the problem, so here it is.

Angular has a number of options for delaying the update to a model based on events in an input field:

<input type="text" name="username"
   ng-model="user.name"
   ng-model-options="{updateOn: 'default blur', 
                      debounce: {default: 500, blur: 0} }" />

(See ng-model options)

Can you delay all the commits to the object based on a user confirmation?

The basic options that Angular offers allows the editing of an input form to be decoupled from the actual update of the model. There are some nice bonuses with this in that we can roll the value of the object back if we decide to cancel that update.

However, I would like to delay the update of the model, not based on an event on the input field but instead based on someone clicking a submit button.

I would ideally like a form where the user can update the inputs (let’s say for a .user form, any bound elements in the page {{user.first_name}} etc. do not update and then when the user clicks submit those updates get committed to the model.

Equally if the user clicks "Cancel" the updates can all be rolled back.

Ideal setup:

<input type="text" name="username"
   ng-model="user.name"
   ng-model-options="{updateOn: 'myCustomEvent' }" />


<button onClick="broadCastMyCustomEventIntoForm()">Save changes</>

Is this possible?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Yes it is possible as long as you bind your input fields to custom event and then trigger that custom event on user confirmation.

http://plnkr.co/edit/GgsaFbIurhx88p6HJgkT?p=preview

<input bind-event type="text" name="userName" ng-model="user.name" ng-model-options="{ updateOn: 'customEvent'}" />

  //bind-event directive for input fields. 
  .directive('bindEvent', function() {
      return {
        restrict: 'EAC',
        controller: function($scope, $element, $attrs) {

          $element.on('customEvent', function() {
            console.log('custom event is triggered');
          });
        }
      };
    });

    //trigger the event on submit.
    $scope.click = function() {
      $element.find( "input" ).triggerHandler( "customEvent" );
    }

Method 2

I found a simple way to do this today using $emit. I was trying to apply filter on a button click, rather than instantly(default behavior):

<input ng-model="myFilter.minPrice" ng-model-options="{updateOn: 'filterBtnClicked'}">

...

<button type="button" ng-click="$emit('filterBtnClicked')">Filter</button>

Model value is applied only after button is clicked.

Method 3

I don’t think angular natively support the use case you describe.

But it shouldn’t be difficult get it done, exposing a copy of the real model to the view and copy the changes to the real model on the click event handler.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply