Create directive for mask

Asked

Viewed 1,572 times

1

I want to wear the mask xx/xx/xxxx in a date field and return in the object with the mask, not only the value. I used a directive ui-mask, but does not return with the mask, already used the model-view-value="true" but it doesn’t work, so I want to create a directive that just takes the value and adds the "//" bars via javascript with substring, only that. But how to use together with ui-mask? by logic, the directive would have to be executed after the date is all typed?

Follow what I’ve done:

angular.module("modulo").directive("uiDate", function ($filter) {
    return {
        require: "ngModel",
        link: function (scope, element, attrs, ctrl) {
            var _formatDate = function (date) {
                date = date.replace(/[^0-9]+/g, "");
                if(date.length > 2) {
                    date = date.substring(0,2) + "/" + date.substring(2);
                }
                if(date.length > 5) {
                    date = date.substring(0,5) + "/" + date.substring(5,9);
                }
                return date;
            };
        }
    };
});

But it still doesn’t work, because the execution of it is not calling according, it is called only when loading the page, it would have to be after the field already has the date, to return only to my ng-model the value with the mask. How would it look?

  • you need to use the directive or would it be a problem to use an external plugin? If you don’t mind, take a look at this: https://github.com/candreoliveira/ngMask is very complete and works well

3 answers

1

Use the function $watch within the link function, where it will observe the changes that occur in the property, and then you can apply the mask logic in the date value.

scope.$watch('propriedade', function (valorAtual, valorAnterior) {
    //código.
});

Documentation for $watch (English)

  • Use for what? Where? How? When?

  • @Celsomtrindade :)

0

worked out good for me like this:

angular.module("aeronaves").directive("uiDate", function() {
    return {
        require: "ngModel",
        link: function (scope, element, attrs, ctrl){
            var _formatDate = function(date){
                date = date.replace(/[^0-9]+/g, "");
                if(date.length > 2) {
                    date = date.substring(0,2) + "/" + date.substring(2);
                }
                if(date.length > 5){
                    date = date.substring(0,5) + "/" + date.substring(5,9);
                }

                return date;
            };

            element.bind("keyup", function (){
                ctrl.$setViewValue(_formatDate(ctrl.$viewValue));
                ctrl.$render();
            });
        }
    };

});

0

You can make the function run whenever the user type, or, put a timeout to run forever n seconds after he stopped typing.

Which to use then?

If you want the user to see the change in real time, use without the timeout. But if there is no problem the user type everything and only after format the date, can use with timeout. Or as you think best.

To do this, just use the method element.onkeypress = function()..., see:

return {
    require: "ngModel",
    link: function (scope, element, attrs, ctrl) {

        element.onkeypress = function() { //É aqui que ele executa a função sempre que uma tecla for pressionada
            var _formatDate = function (date) {
                date = date.replace(/[^0-9]+/g, "");
                if(date.length > 2) {
                    date = date.substring(0,2) + "/" + date.substring(2);
                }
                if(date.length > 5) {
                    date = date.substring(0,5) + "/" + date.substring(5,9);
                }
                return date;
            };
        } //finaliza o element.onkeypress

    }
};

Or, if you will use with timeout, use as follows:

element.onkeypress = function() {
    $timeout(function(){
        var _formatDate = function(date) {
        //... restante do código aqui
    }, 1000);
}

Why am I giving this answer and what it differs from the previous answer, which uses the $watch?

There is much controversy in the use of property $watch when we refer to performance, since it is associated with the firing of the $digest, which is the cycle that updates all variables of $scope of your page. So, the more variables you own, the heavier your application will be with the use of $watch, since it will need to analyze all variables whenever the field changes value.

The method onkeypress does not go through this, because it depends on the values of variables, it depends only on the interaction with the field.

  • the function is called correctly, but does not return the value for ngModel.

  • debugging saw that the date stays as I want, but it is not setando no ngModel

  • Try to add scope:true before starting the link

  • continues to return without the bars, but debugging Return already has the correct date, but is not in ngmodel

  • I’ll do some tests here and soon return.

  • OK, I’ll be waiting...

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.