Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angularjs change ng-model within a directive on the same element with validations

In the most primitive angular app I am trying to create a directive for an input field which changes parent's ng-model value.

HTML:

<form novalidate>
  <input ng-model="ctrl.myvalue" mydirective minlength="19" />

  {{ ctrl.myvalue }}
</form>

JS:

var app = angular.module('app', []);

app.directive('mydirective', function(){
    return {
        scope: { ngModel: '=' },
        link: function(scope, el) {
           el.on('input', function(e) {
              this.value = this.value.replace(/ /g,'');

              scope.ngModel = this.value;
           })
        }
    }
})

app.controller('MyController', function(){
  this.myvalue = '';
})

Plunker

The problem is that if I use this directive together with minlength or pattern for an input validation it gets a specific behavior: every second letter you type in the input disappears; also ng-model gets undefined value. Without validations the code works perfectly.

I also tried to create a custom validation as a workaround but it has the same effect.

Could you explain that or propose the way to go?

like image 646
smnbbrv Avatar asked Feb 25 '26 11:02

smnbbrv


1 Answers

You can use unsift, as well render for the first iteration. Usually you can use ctrl.$setViewValue but you can be sure no relaunch when the value don;t change...

var testModule = angular.module('myModule', []);

testModule.controller('testCntrl', ['$scope', function ($scope) {
    $scope.test = 'sdfsd  fsdf sdfsd sdf';

}]);

testModule.directive('cleanSpaces', [function () {
    return {
        require: '?ngModel',
        link: function (scope, $elem, attrs, ctrl) {
            if (!ctrl) return;

            var filterSpaces = function (str) {
                return str.replace(/ /g, '');
            }

            ctrl.$parsers.unshift(function (viewValue) {

                var elem = $elem[0],
                    pos = elem.selectionStart,
                    value = '';

                if (pos !== viewValue.length) {
                    var valueInit = filterSpaces(
                    viewValue.substring(0, elem.selectionStart));
                    pos = valueInit.length;
                }

                //I launch the regular expression, 
                // maybe you prefer parse the rest 
                // of the substring and concat.

                value = filterSpaces(viewValue);
                $elem.val(value);

                elem.setSelectionRange(pos, pos);

                ctrl.$setViewValue(value);

                return value;
            });

            ctrl.$render = function () {
                if (ctrl.$viewValue) {
                    ctrl.$setViewValue(filterSpaces(ctrl.$viewValue));
                }
            };
        }
    };
}]);

http://jsfiddle.net/luarmr/m4dmz0tn/

UPDATE I update the fiddle with the last code and a validation example in angular and update the html with ng-trim (ngModel.$parsers ingore whitespace at the end of ng-model value).

like image 178
Raúl Martín Avatar answered Feb 27 '26 23:02

Raúl Martín



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!