Why ngModel's $render is not called when the model changes in AngularJS?

12,225

Solution 1

The input directive is running after your directive and thus it's $render function is replacing yours.

Set your directive's priority to something greater than 0. For instance:

.directive("phoneNumber", function() {
  return {
    restrict: 'A',
    require: 'ngModel',
    priority: 1,
    link: function(scope, element, attrs, ngModel) {
      ngModel.$render = function() {
        alert('rendering');
      };
    } 
  };
});

And your $render will take precedence and you'll see your alert is called.

Solution 2

ngModel.$render is working, when calling $render in the $apply.

app.directive('changecase', function ($timeout) {
    return {
    restrict: 'A',
    require: 'ngModel',
    priority: 1,
    link: function (scope, element, attrs, ngModel) {
      
        //format text going to user (model to view)
        ngModel.$formatters.push(function(value) {
            return value.toUpperCase();
        });

        //format text from the user (view to model)
        ngModel.$parsers.push(function(value) {
            return value.toUpperCase();
        });

        element.on('blur keyup change', function() {
            scope.$apply(function(){
              ngModel.$setViewValue(ngModel.$modelValue);
              ngModel.$render();
            });
            });
        }
    }
});

Share:
12,225

Related videos on Youtube

Misha Moroshko
Author by

Misha Moroshko

I build products that make humans happier. Previously Front End engineer at Facebook. Now, reimagining live experiences at https://muso.live

Updated on June 06, 2022

Comments

  • Misha Moroshko
    Misha Moroshko about 2 years

    DEMO

    Why in the following example $render is not called when the button is clicked?

    <input type="text" ng-model="client.phoneNumber" phone-number>
    <button ng-click="client.phoneNumber='1111111111'">Change phone number</button>
    
    .directive("phoneNumber", function() {
      return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attrs, ngModel) {
          ngModel.$render = function() {
            alert('rendering');   // This is not called
          };
        } 
      };
    }); 
    
  • Misha Moroshko
    Misha Moroshko over 10 years
    Thanks! Makes perfect sense now.
  • KayakDave
    KayakDave over 10 years
    You're welcome! You can check out the Angular input directive here - it can help a lot seeing how it uses $render
  • Laurent
    Laurent over 9 years
    Works, calling 'render', but the input text in losing it's value: it is becoming empty. Any idea why?
  • nicoabie
    nicoabie over 9 years
    this is the actual cause github.com/angular/angular.js/blob/master/src/ng/… for the same priority angular sorts by name with no warning (facepalm)
  • MarkHoward02
    MarkHoward02 over 9 years
    Thank you. Still unsure about Angular Directives. Quite frustrating to program.
  • NIKHIL NEDIYODATH
    NIKHIL NEDIYODATH about 3 years
    using priority 10 might be more reliable