Angular Directives with methods of constructing objects

4

I'm trying to create a directive that is an input that makes an object available in $ scope only if it is successfully created by its constructor method.

I want the value to be assigned only to the variable in the scope if it is the result of an object constructor, which encapsulates the build / validation rules in its constructor.

Next to the input, the directive must have a span, where it will display validation error. If the constructor does not validate the value, an exception must be generated and displayed in a field to the side, such as validation.

Here, I've created a Cpf object, which encapsulates its rules. The angle directive provides an input that generates the object in $ scope only if it is created successfully.

I created this Direcive and it works. However, the restrict: Element type does not allow reuse as well as a component. I can not declare a placeholder in my custom element, or other things I could apply directly in the input.

I'd like to know how to make it into a more modular policy.

Maybe of Attribute type, so I can decorate the input with other attributes, such as placeholder, or a mask. Or, use ngModel to know which variable to put the instantiated object in.

//-------------Angular---------------------->

        var app = angular.module('teste', []);
        
//Diretiva:

        app.directive('sgInputModel', function(){
            return {
                restrict: 'E',
                scope: {
                    set : '&onSet'
                },
                template: '<input ng-model="modelo" ><span ng-bind="modeloErro"></span>',
                link: function(scope, element, attrs){
                    scope.$watch('modelo', setModelo);
                    function setModelo(){
                        console.log(scope.modelo)
                        scope.modeloErro = '';
                        if(!scope.modelo)
                            return;
                        try{
                            scope.set({value:scope.modelo});
                        }catch(e){
                            scope.modeloErro = e.message;
                        }
                    }
                }
            }
        });

//Controller:

        app.controller('pedidoCtl', [
            '$scope',
            '$http',
            '$log',
            function ($scope, $http, $log, URL_SELECT) {
              
              $scope.sgSetCpf = function (value){
                    $scope.cpf = null;
                    if(value.length == 11)
                        $scope.cpf = new Cpf(value);
                };
              
              }]);



//-------------Objeto CPF---------------------->

    Cpf = function (cpf) {
        cpf = retirarCaracteres(cpf);
        if (!this.validar(cpf))
            throw new CpfException('Cpf inválido');
        Object.defineProperty(this, 'cpf', {
            value: cpf
        });
        
        if(!Cpf.instances[this.formatado]){
            Cpf.instances[this.formatado] = this;
        }
        else
            return Cpf.instances[this.formatado];
    };
    
    Cpf.instances = [];

    Object.defineProperties(Cpf.prototype, {
        formatado: {
            get: function(){
                return this.cpf.replace(/^(\d{3})(\d{3})(\d{3})(\d{2})$/,"$1.$2.$3-$4");
            }
        },
        validar: {
            value: function(cpf){
                cpf = String(cpf);
                var numeros, digitos, soma, i, resultado, digitos_iguais;
                digitos_iguais = 1;
                if (cpf.length < 11)
                    return false;
                for (i = 0; i < cpf.length - 1; i++)
                    if (cpf.charAt(i) != cpf.charAt(i + 1))
                    {
                        digitos_iguais = 0;
                        break;
                    }
                if (!digitos_iguais)
                {
                    numeros = cpf.substring(0, 9);
                    digitos = cpf.substring(9);
                    soma = 0;
                    for (i = 10; i > 1; i--)
                        soma += numeros.charAt(10 - i) * i;
                    resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;
                    if (resultado != digitos.charAt(0))
                        return false;
                    numeros = cpf.substring(0, 10);
                    soma = 0;
                    for (i = 11; i > 1; i--)
                        soma += numeros.charAt(11 - i) * i;
                    resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;
                    if (resultado != digitos.charAt(1))
                        return false;
                    return true;
                }
                else
                    return false;
            }
        }
    });

    Cpf.prototype.toString = function () {
        return this.formatado;
    };
    
    Cpf.prototype.valueOf = function(){
        return Number(this.ano + this.mes);
    };
    
    
    function CpfException(message) {
      this.name = 'CpfException';
      this.message= message;
    }
    CpfException.prototype = new Error();
    CpfException.prototype.constructor = CpfException;

    function retirarCaracteres(string){
      return String(string).replace(/\D/g, '');
    }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script><bodyng-app="teste" ng-controller="pedidoCtl">
  
        Cpf:
        <sg-input-model 
            on-set="sgSetCpf(value)"
        ></sg-input-model>
        {{cpf.formatado}}
  
</body>
    
asked by anonymous 11.12.2014 / 03:55

1 answer

1

You could put more variables in the scope and be passing them to the placeholder, for example.

You would also have to modify your template to accept this placeholder.

You could put all the attributes of an input in the scope and pass them through the scope.

    
17.12.2014 / 15:47