filtros no modelo ng em uma input

Eu tenho uma input de texto e não quero permitir que os usuários usem espaços, e tudo que for typescript será transformado em minúsculas.

Eu sei que não tenho permissão para usar filtros no ng-modelo, por exemplo.

ng-model='tags | lowercase | no_spaces' 

Eu olhei para criar minha própria diretiva mas adicionando funções a $parsers e $formatters não atualizaram a input, apenas outros elementos que tinham ng-model nela.

Como posso alterar a input de que estou digitando atualmente?

Eu estou essencialmente tentando criar o recurso ‘tags’ que funciona exatamente como o aqui no StackOverflow.

    Eu sugeriria observar o valor do modelo e atualizá-lo em chage: http://plnkr.co/edit/Mb0uRyIIv1eK8nTg3Qng?p=preview

    O único problema interessante é com espaços: No AngularJS 1.0.3 ng-model na input apara automaticamente a string, por isso não detecta que o modelo foi alterado se você adicionar espaços no final ou no início (para que os espaços não sejam removidos automaticamente pelo meu código). Mas em 1.1.1 existe uma diretiva ‘ng-trim’ que permite desabilitar essa funcionalidade ( commit ). Então, decidi usar o 1.1.1 para obter a funcionalidade exata que você descreveu na sua pergunta.

    Acredito que a intenção das inputs AngularJS e do ngModel direcive é que a input inválida nunca deve acabar no modelo . O modelo deve ser sempre válido. O problema de ter um modelo inválido é que podemos ter observadores que triggersm e executam ações (inadequadas) com base em um modelo inválido.

    Do meu ponto de vista, a solução adequada é conectar-se ao pipeline $parsers e garantir que a input inválida não seja incluída no modelo. Não sei como você tentou abordar as coisas ou o que exatamente não funcionou para você com os $parsers mas aqui está uma diretiva simples que resolve seu problema (ou pelo menos minha compreensão do problema):

     app.directive('customValidation', function(){ return { require: 'ngModel', link: function(scope, element, attrs, modelCtrl) { modelCtrl.$parsers.push(function (inputValue) { var transformedInput = inputValue.toLowerCase().replace(/ /g, ''); if (transformedInput!=inputValue) { modelCtrl.$setViewValue(transformedInput); modelCtrl.$render(); } return transformedInput; }); } }; }); 

    Assim que a diretiva acima for declarada, ela pode ser usada assim:

      

    Como na solução proposta por @Valentyn Shybanov, precisamos usar a diretiva ng-trim se quisermos desabilitar espaços no início / final da input.

    A vantagem desta abordagem é dupla:

    • Valor inválido não é propagado para o modelo
    • Usando uma diretiva, é fácil adicionar essa validação personalizada a qualquer input sem duplicar os observadores repetidas vezes.

    Uma solução para este problema poderia ser aplicar os filtros no lado do controlador:

    $scope.tags = $filter('lowercase')($scope.tags);

    Não se esqueça de declarar $filter como dependência.

    Eu tive um problema semelhante e usado

     ng-change="handler(objectInScope)" 

    no meu manipulador eu chamo um método do objectInScope para modificar-se corretamente (input grosseira). No controlador eu iniciei em algum lugar que

     $scope.objectInScope = myObject; 

    Eu sei que isso não usa nenhum filtro ou observador de fantasia … mas é simples e funciona muito bem. O único lado negativo disso é que o objectInScope é enviado na chamada para o manipulador …

    Use uma diretiva que inclua as collections $ formatters e $ parsers para garantir que a transformação seja executada nas duas direções.

    Veja esta outra resposta para mais detalhes incluindo uma binding a jsfiddle.

    Se você estiver usando o campo de input somente leitura, poderá usar ng-value com filter.

    por exemplo:

     ng-value="price | number:8" 

    Você pode tentar isso

     $scope.$watch('tags ',function(){ $scope.tags = $filter('lowercase')($scope.tags); }); 

    Se você estiver fazendo uma validação complexa de input assíncrona, pode valer a pena abstrair o ng-model em um nível como parte de uma class customizada com seus próprios methods de validação.

    https://plnkr.co/edit/gUnUjs0qHQwkq2vPZlpO?p=preview

    html

     

    código

     (function() { const _ = window._; angular .module('app', []) .directive('componentLayout', layout) .controller('Layout', ['Validator', Layout]) .factory('Validator', function() { return Validator; }); /** Layout controller */ function Layout(Validator) { this.store = { a: new Validator({title: 'input a'}), b: new Validator({title: 'input b'}) }; } /** layout directive */ function layout() { return { restrict: 'EA', templateUrl: 'layout.html', controller: 'Layout', controllerAs: 'vm', bindToController: true }; } /** Validator factory */ function Validator(config) { this.model = null; this.isValid = null; this.title = config.title; } Validator.prototype.isEmpty = function(checkName) { return new Promise((resolve, reject) => { if (/^\s+$/.test(this.model) || this.model.length === 0) { this.isValid = false; this.warning = `${this.title} cannot be empty`; reject(_.merge(this, {test: checkName})); } else { this.isValid = true; resolve(_.merge(this, {test: checkName})); } }); }; /** * @memberof Validator * @param {array} checks - array of strings, must match defined Validator class methods */ Validator.prototype.validate = function(checks) { Promise .all(checks.map(check => this[check](check))) .then(res => { console.log('pass', res) }) .catch(e => { console.log('fail', e) }) }; })();