Getting angular directive attribute value returns 'undefined'

15,788

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

Share:
15,788
Fals
Author by

Fals

Software Architect, I do love the Web, Patterns, Agile, DevOps and the new Microservice trend

Updated on June 14, 2022

Comments

  • Fals
    Fals about 2 years

    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?

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