0
votes

I want to add an 'ng-pattern' directive to an input element through a custom directive. I don't want to do it in the templates directly, but it looks I'm getting in a infinite loop.

I tried to set first the 'html' and compile the element after (Angular compile in directive seems to go into infinite loop) but scope is undefined. I don't know if it's related with replacing element's content.

Should i create a new scope? Do I'm missing something?

Thanks in advance!

                    var myHtml = iElem[0].outerHTML;
                    iElem.replaceWith(myHtml);
                    var compiledElement = $compile(iElem)(iElem.scope());

HTML:

<input type="text" ng-model="personal.testNumber_string" my-model="personal.testNumber" dot-to-comma>

Directive:

function dotToCommaConverter($compile) {
    return {
        require: 'ngModel',
        restrict: 'A',
        scope: {
            myModel: '='
        },
        controllerAs: 'dot2Comma',

        controller: function($scope) {

            this.myModel = $scope.myModel;
        },


        compile: function(tElem, tAttrs) {

            return {
                pre: function(scope, iElem, iAttrs) {


                },
                post: function(scope, iElem, iAttrs, modelCtrl) {

                    iElem.attr('ng-pattern', '/^-?[0-9]+(?:\,[0-9]+)?$/');
                    var compiledElement = $compile(iElem)(iElem.scope());
                    iElem.replaceWith(compiledElement);


                    modelCtrl.$setViewValue(String(scope.dot2Comma.myModel).replace('.', ','));
                    modelCtrl.$render();


                    modelCtrl.$parsers.push(function(inputValue) {

                        var transformedInput = inputValue.replace(/[^0-9,.-]/g, '');
                        transformedInput = transformedInput.replace('.', ',');
                        transformedInput = transformedInput.replace(' ', '');

                        if (transformedInput !== inputValue) {

                            modelCtrl.$setViewValue(transformedInput);
                            modelCtrl.$render();
                        }

                        if (!isNaN(Number(transformedInput.replace(',', '.')))) {
                            scope.myModel = Number(transformedInput.replace(',', '.'));
                        } else {
                            scope.myModel = undefined;
                        }

                        return transformedInput;
                    });
                }
            };
        }
    };
}
2

2 Answers

1
votes

I needed to remove my own directive from the Html content before re-compiling again, that's what caused the infinite loop.

                    iElem.removeAttr('dot-to-comma');
                    iElem.attr('ng-pattern', '/^-?[0-9]+(?:\,[0-9]+)?$/');
                    iElem.attr('ng-blur', 'dot2Comma.myBlurFunction()');

                    var compiledElement = $compile(iElem)(scope);
                    iElem.replaceWith(compiledElement);
0
votes

here is an sample directive which replace dots with commas in a textbox :

script.js

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

angular.module('app')
 .controller('ExampleController', ['$scope', function($scope) {
   $scope.my = { number: '123.456' };
 }]);

 angular.module('app')
 .directive('dotToComma', function() {
   return {
    restrict: 'A',
        link: function (scope, element, attrs) {
            scope.$watch(attrs.ngModel, function (value) {
                var newValue = value.replace('.', ',');
                element.val(newValue);
            });
        }
   }
 });

index.html

<html lang="en" ng-app="app">
<head>
  <meta charset="utf-8">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
  <script src="script.js"></script>
</head>

<body>
    <form ng-controller="ExampleController">

    <p>scope.my.number = {{my.number}}</p>

    <label>In this textbox, dots will automatically be replaced with commas, even if you change its value :</label>
    <input type="text" ng-model="my.number" dot-to-comma>
 </form>
</body>
</html>

Here is a plunker : https://plnkr.co/edit/X6Fi0tnjBXKKhbwH0o2q?p=preview

Hope it helps !