filtry na ng-model na wejściu

Mam wejście tekstowe i nie chcę zezwalać użytkownikom na używanie spacji, a wszystko wpisane zostanie zamienione na małe litery.

Wiem, że nie wolno mi używać filtrów na ng-model np.

ng-model='tags | lowercase | no_spaces'

Patrzyłem na stworzenie własnej dyrektywy, ale dodawanie funkcji do $parsers i $formatters nie aktualizowało danych wejściowych, tylko inne elementy, które miały na sobie ng-model.

Jak mogę zmienić dane wejściowe, które aktualnie wpisuję?

Zasadniczo staram się stworzyć funkcję 'tags', która działa tak samo jak ten tutaj na StackOverflow.

Author: georgeawg, 2013-01-20

8 answers

Proponuję obejrzeć wartość modelu i zaktualizować ją po chage: http://plnkr.co/edit/Mb0uRyIIv1eK8nTg3Qng?p=preview

Jedyny interesujący problem to spacje: w AngularJS 1.0.3 ng-model na wejściu automatycznie przycina ciąg znaków, więc nie wykrywa, że model został zmieniony, jeśli dodasz spacje na końcu lub na początku (więc spacje nie są automatycznie usuwane przez mój kod). Jednak w 1.1.1 istnieje dyrektywa 'ng-trim', która pozwala na wyłączenie tej funkcjonalności (commit). Więc Zdecydowałem się użyć 1.1.1, aby osiągnąć dokładną funkcjonalność opisaną w twoim pytaniu.

 28
Author: Valentyn Shybanov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-19 23:42:52

Uważam, że intencją wejścia AngularJS i ngModel jest to, że nieprawidłowe wejście nigdy nie powinno skończyć się w modelu. Model powinien być zawsze ważny. Problem z nieprawidłowym modelem polega na tym, że możemy mieć obserwatorów, którzy odpalają i podejmują (niewłaściwe) działania w oparciu o nieprawidłowy model.

Jak widzę, właściwym rozwiązaniem jest podłączenie do $parsers potoku i upewnienie się, że nieprawidłowe dane wejściowe nie trafią do modelu. Nie wiem, jak próbowałeś. podejście rzeczy lub co dokładnie nie działa dla ciebie z $parsers ale tutaj jest prosta dyrektywa, która rozwiązuje twój problem (a przynajmniej moje zrozumienie problemu): {]}

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;         
       });
     }
   };
});

Jak tylko powyższa dyrektywa zostanie zadeklarowana, może być użyta w następujący sposób:

<input ng-model="sth" ng-trim="false" custom-validation>

Tak jak w rozwiązaniu zaproponowanym przez @ Valentyn Shybanov, musimy użyć dyrektywy ng-trim, jeśli chcemy zablokować spacje na początku / końcu wejścia.

Zaletą tego podejścia jest 2-krotność:

  • Invalid wartość nie jest propagowana do modelu
  • używając dyrektywy, łatwo jest dodać tę niestandardową walidację do dowolnego wejścia bez powielania obserwatorów w kółko
 200
Author: pkozlowski.opensource,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-01 13:45:19

Rozwiązaniem tego problemu może być zastosowanie filtrów po stronie kontrolera:

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

Nie zapomnij zadeklarować $filter jako zależności.

 21
Author: Pierre-Yves Le Dévéhat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-14 11:16:05

Użyj dyrektywy, która dodaje do kolekcji $formatters i $ parsers, aby upewnić się, że transformacja jest wykonywana w obu kierunkach.

Zobacz ta inna odpowiedź Aby uzyskać więcej szczegółów, w tym link do jsfiddle.

 4
Author: Scott Munro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:20

Miałem podobny problem i używałem

ng-change="handler(objectInScope)" 

W moim programie obsługi wywołuję metodę objectInScope, aby zmodyfikować się poprawnie (gruboziarniste wejście). W kontrolerze zainicjowałem gdzieś, że

$scope.objectInScope = myObject; 

Wiem, że to nie używa żadnych fantazyjnych filtrów lub obserwatorów... ale to proste i działa świetnie. Jedynym powodem tego jest to, że obiektinscope jest wysyłany w wywołaniu do obsługi...

 3
Author: wojjas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-07 17:25:12

Jeśli używasz pola tylko do odczytu, możesz użyć ng-value z filtrem.

Na przykład:

ng-value="price | number:8"
 3
Author: Edward D. Wilson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-10 22:36:55

Możesz spróbować tego

$scope.$watch('tags ',function(){

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

});
 0
Author: Nikhil Mahirrao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-19 06:50:12

Jeśli wykonujesz skomplikowaną, asynchroniczną walidację wejściową, może być warto abstrakcyjnie ng-model podnieść poziom o jeden poziom jako część niestandardowej klasy z własnymi metodami walidacji.

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

Html

<div>

  <label for="a">input a</label>
  <input 
    ng-class="{'is-valid': vm.store.a.isValid == true, 'is-invalid': vm.store.a.isValid == false}"
    ng-keyup="vm.store.a.validate(['isEmpty'])"
    ng-model="vm.store.a.model"
    placeholder="{{vm.store.a.isValid === false ? vm.store.a.warning : ''}}"
    id="a" />

  <label for="b">input b</label>
  <input 
    ng-class="{'is-valid': vm.store.b.isValid == true, 'is-invalid': vm.store.b.isValid == false}"
    ng-keyup="vm.store.b.validate(['isEmpty'])"
    ng-model="vm.store.b.model"
    placeholder="{{vm.store.b.isValid === false ? vm.store.b.warning : ''}}"
    id="b" />

</div>

Kod

(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) })
  };

})();
 0
Author: Daniel Lizik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-02 17:24:13