Arno_Geismar
Arno_Geismar

Reputation: 2330

ngModel does not trigger view update the first time

Hi I am writing a directive that does some custom input element validation based on a json object that is passed via an attribute directive. I am adding an ng-blur and ng-focus in the compile phase binding to two functions in my directive controller. however. when I run my code initially the input field does not contain a value altough when I click in it and the blur is triggered I can see in debug that ngModel does contain the value. I am thinking that the view is not updated the first time but I don't understand what is causing it. Here is my code.

    'use strict';

angular.module('zendantennesApp')
    .directive('validation', function ($compile, $parse) {
        return {
            scope: {
                validation: '@'
            },
            require: "?ngModel",
            restrict: 'A',
            compile: function(el, attrs) {
                el.removeAttr('validation');
                el.attr('ng-blur', 'evaluateExpression()');
                el.attr('ng-focus', 'assignOriginalValue()');
                var fn = $compile(el);
                return function(scope, element, attrs, ngModel){
                    ngModel.$render = function(){
                    $(element).val(ngModel.$viewValue);
                    };



                fn(scope);
            }
        },
        controller: function($scope){
            $scope.originalValue = $scope.ngModel;
            $scope.validationObject = JSON.parse($scope.validation.replace(/'/g, '"'));
            $scope.evaluateExpression = function(){
                console.log(validationObject);
            };
            $scope.assignOriginalValue = function(){
                $scope.originalValue = $scope.ngModel;

            }
        }
    }
});

my html:

<input validation="{'min':0, 'max':5}" tabindex="45" type='text' class='form-control' ng-model="aanpassing.nieuweAntenne.elektrischeTilt"/>

I added a plunkr to illustrate the problem:

https://plnkr.co/edit/1qYxCiSZWHgVeN9CEpxw?p=info

if anyone could help that would be greatly appreciated

Upvotes: 1

Views: 753

Answers (1)

Gustav
Gustav

Reputation: 3586

The plunkr I provided in the comment seems to work, so I'll put it as a answer.

Instead of using compile on the directive it is possible to use the linking function directly:

app.directive('validation', function ($compile, $parse) {
    return {
        scope: {
            validation: '@'
        },
        require: "ngModel",
        restrict: 'A',
        link:  function(scope, element, attrs, ngModel){
            scope.validation = scope.validation.replace(/'/g, '"');
            var validation = JSON.parse(scope.validation);
            for(prop in validation){
              if(validation.hasOwnProperty(prop)){
                setUpValidators(prop);
              }
            }
            function setUpValidators(val){
                switch(val){
                 case 'min': 
                   ngModel.$validators.min = function(modelValue, viewValue){
                      var value = modelValue || viewValue;
                      return value.length >= validation.min;
                   };
                   break;
                 case 'max':{
                   ngModel.$validators.min = function(modelValue, viewValue){
                     var value = modelValue || viewValue;
                     return value.length <= validation.max;
                    };
                    break;
                  }
                 }
            }
            ngModel.$render = function(){
                element.val(ngModel.$viewValue);
            };
        }
    };
});

This will set up validator on the ngModel based on the provided object to the validate-directive. If you want to wait with validating until after the input is blurred you could use ngModelOptions like this: ng-model-options="{updateOn: 'blur'}" on the input element.

When doing like this you don't need to add any ng-blur or ng-focus on the element in the compile step.

Upvotes: 1

Related Questions