2

I'm doing a directive for input mask. But, when I pass a string as value the attribute is undefined. If I pass directly the mask It's working.

.directive('inputMask', function () {
return {
    restrict: 'EAC',
    scope: true,
    link: function (scope, element, attrs) {
        scope.$watch('inputMask', function (newVal) {
            console.log('inputMask', newVal);
        });
        var maskType = scope.$eval(attrs.inputMask);
        switch (maskType) {
            case 'phone':
                $(element).inputmask("phone", {
                    url: '@Url.Content("~/Scripts/jquery-inputmask/phone-codes/phone-codes.json")',
                    onKeyValidation: function () { //show some metadata in the console
                        console.log($(this).inputmask("getmetadata")["name_en"]);
                    }
                });
                break;
            case 'money':
                $(element).inputmask("decimal", { digits: 2 });
                break;
            case 'moneyGrouped':
                $(element).inputmask("decimal", {
                    radixPoint: ",",
                    autoGroup: true,
                    groupSeparator: ".",
                    groupSize: 3,
                    digits: 2
                });
                break;
            case 'email':
                $(element).inputmask('Regex', { regex: "[a-zA-Z0-9._%-]+@[a-zA-Z0-9-]+\\.[a-zA-Z]{2,4}" });
            default:
                $(element).inputmask(maskType);
        }

        $(element).inputmask(scope.$eval(attrs.inputMask));
        $(element).on('keypress', function () {
            scope.$eval(attrs.ngModel + "='" + element.val() + "'");
        });
    }
};
});

Working (will get into default of the switch):

<input type="teste" name="teste" value="" ng-model="form.email" input-mask='{ "mask": "d/m/y", "autoUnmask" : true}'/>

Not working, attrs.inputMask is undefined (should enter in case 'money'):

<input type="teste" name="teste" value="" ng-model="form.email" input-mask='money'/>

What is wrong?

3
  • 2
    This isn't your answer, but for googlers one thing to check is your camelcased scope parameters are expected to be spinal case in html when using shorthand syntax '=' Commented Jul 27, 2015 at 23:08
  • Please do this in your $watch - console.log(typeof newVal);, and check for two cases. Please revert back then I may solve the problem. Or provide a fiddle for this. Commented Oct 30, 2015 at 11:13
  • thanks, fiat! this was the problem in my case Commented Sep 28, 2017 at 1:52

3 Answers 3

3

When you use scope: true a new scope will be created for this directive. Then, to your $watch works correctly, you should create a new attribute to the current scope, called inputMask, that receives the attrs.inputMask

scope.inputMask = attrs.inputMask;
scope.$watch('inputMask', function (newVal) {
    console.log('inputMask', newVal);
});

You can see a simplified Working fiddle here

The other option, is to use the a hash object in directive's scope attribute.

The directive docs writes:

{} (object hash) - a new 'isolate' scope is created. The 'isolate' scope differs from normal scope in that it does not prototypically inherit from the parent scope. This is useful when creating reusable components, which should not accidentally read or modify data in the parent scope.

(...)

@ or @attr - bind a local scope property to the value of a DOM attribute.

That way, you can create your scope binding the DOM attribute:

scope: { 
    inputMask: "@" 
},
link: function (scope, element, attrs) {
    scope.$watch('inputMask', function (newVal) {
        console.log('inputMask', newVal);
    });
    /* ... */
}

Fiddle

Sign up to request clarification or add additional context in comments.

3 Comments

attrs.inputMask still undefined using this.
Did you check the fiddles? What is your angular version?
check your self, just write the value of inputMask when you set as inputMask='phone' for exemple, is undefined
0

In the directive use,

scope: {inputMask: '@'}

And in the link function instead of using attr.inputMask use scope.inputMask and that will work.

If you want to use attr then you can use

attr.$observe('inputMask', function() {
    console.log('changed');
}

Because initially the value will be undefined.

Comments

0

The actual problem here was that scope.$eval('money') will return undefined. The attribute should be linking just fine to the directive, if it's in curly braces {}, or if it's a string such as 'money'.

It's what you're doing with the value that's causing the problem.

var maskType = scope.$eval(attrs.inputMask);

You would only need to use isolated scope with @, or attrs.$observe if you were passing interpolated attributes, such as {{money}}.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.