Alejandro Plaza
Alejandro Plaza

Reputation: 31

Custom directive that sets a custom directive attribute on the element

I'm using ui-mask from AngularJS-UI. I want to set the attribute dynamically depending on the HTML input type.

This is how you normally use this directive:

<input type="tel" class="form-control" 
      ng-model="Model.Homephone" placeholder="Home Phone" 
      ui-mask="(999) 999-9999" ui-mask-placeholder/>

It works fine like that. Now, I created a directive that just adds this attribute with it's value depending on the input type.

Custom Directive:

angular.module('App').directive("uiMaskType", ['$log', function ($log) {
return {
    restrict: "A",
    require: 'ngModel',
    link: function (scope, element, attributes, ngModel) {

        $log.log(element.attr('type'));

        switch(element.attr('type')) {
            case 'tel':
                element.attr('ui-mask', '(999) 999-9999');
                break;
            case 'text':
                element.attr('ui-mask', '999-99-9999');
                break;
        }
    }
};
}]);

I use the directive inside the input element like this:

<input type="tel" class="form-control" 
       ng-model="Model.Homephone" placeholder="Home Phone" 
       ui-mask-type ui-mask-placeholder/>

When I run the page the result is this:

<input type="tel" class="form-control" 
       ng-model="Model.Homephone" placeholder="Home Phone" 
       ui-mask-type ui-mask-placeholder ui-mask="(999) 999-9999"/>

Even though the attribute is there, the masking is not working. I checked the AngularJS-UI's mask.js file for the directive's priority and tried to set mine higher so that it adds the attribute before compiling the ui-mask. Anyone have an idea what could be the problem?

Upvotes: 0

Views: 1293

Answers (1)

AWolf
AWolf

Reputation: 8990

You have to compile your added attributes and add it to your directive. Also remove ui-mask-type before compilation to avoid an endless loop.

I would change type to mask-type or any other name to avoid a conflict with type of input tag.

terminal: true is needed in my demo to have it working not exactly sure why but I think with-out it there is a problem with the ui-mask-placeholder directive. That is re-running at ever char you're typing. terminal will stop execution of other directives with lower priority.

Please have a look at the demo below or in this fiddle.

angular.module('App', ['ui.mask'])
    .directive("uiMaskType", ['$log', '$compile', function ($log, $compile) {
return {
    restrict: "A",
    priority: 200,
    terminal: true,
    //replace: true,
    link: function (scope, element, attributes) {

        $log.log(element.attr('mask-type'));

        switch(element.attr('mask-type')) {
            case 'tel':
                element.attr('ui-mask', '(999) 999-9999');
                break;
            case 'text':
                element.attr('ui-mask', '999-99-9999');
                break;
        }
        element[0].removeAttribute('ui-mask-type'); // remove our attribute dir. to avoid infinte loop
        //element.attr('ui-mask-placeholder','');

        console.log(attributes, element);
        element.replaceWith($compile(element)(scope));
    }
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdn.rawgit.com/angular-ui/ui-mask/master/dist/mask.js"></script>

<div ng-app="App">
    <input mask-type="text" class="form-control" ng-model="Model.text" placeholder="Enter text" ui-mask-type="" ui-mask-placeholder/>
    <input mask-type="tel" class="form-control" ng-model="Model.homePhone" placeholder="Home Phone" ui-mask-type="" ui-mask-placeholder=""/>
  
   <pre>{{Model | json: 2}}</pre>
</div>

Upvotes: 1

Related Questions