Вопрос по angularjs-filter, dom-manipulation, angularjs-ng-model, angularjs – фильтры по ng-модели во входе

121

У меня есть текстовый ввод, и я неЯ не хочу, чтобы пользователи могли использовать пробелы, и все напечатанное будет превращено в строчные.

Я знаю я'Нельзя использовать фильтры на модели ng, например.

ng-model='tags | lowercase | no_spaces'

Я посмотрел на создание своей собственной директивы, но добавление функций в$parsers а также$formatters А не было»обновить ввод, только другие элементы, которые имелиng-model в теме.

Как я могу изменить ввод этого яя сейчас набираю?

м по сути пытается создатьтеги функция, которая работает так же, как здесь, на StackOverflow.

Посмотрите, помогает ли использование $ timeout (..., 0) с ng-change:stackoverflow.com/questions/12176925/... Mark Rajcok

Ваш Ответ

8   ответов
4

которая добавляет оба к коллекциям $ formatters и $ parsers, чтобы гарантировать, что преобразование выполняется в обоих направлениях.

Увидетьэтот другой ответ для более подробной информации, включая ссылку на jsfiddle.

23

оллера:

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

Дон»не забудьте объявить$filter как зависимость.

Ты нене должен нравиться мой ответ, но это неэто не значитS не так. Проверьте свое эго, прежде чем понизить голос. icfantv
это выполняется только один раз. и добавление к часам не является правильным решением, потому что даже на начальном этапе модель становится недействительной - правильное решение - добавить к модели ».парсеры icfantv
Но ты'Мне нужно $ смотреть на него, если вы хотите, чтобы он обновлялся правильно. Mr Mikkél
Я думаю это'правильный ответ wukong
5

Если вы используете поле ввода только для чтения, вы можете использовать ng-значение с фильтром.

например:

ng-value="price | number:8"
201

ngModel это то, чтоневерный ввод никогда не должен заканчиваться в модели, Модель всегда должна быть действительной. Проблема с недопустимой моделью заключается в том, что у нас могут быть наблюдатели, которые запускают и выполняют (неуместные) действия на основе недопустимой модели.

На мой взгляд, правильным решением здесь является подключение к$parsers конвейер и убедитесь, что неверный ввод несделать это в модели. Я'я не уверен, как ты пытался приблизиться к вещам или что именноработать на тебя с$parsers но вот простая директива, которая решает вашу проблему (или, по крайней мере, мое понимание проблемы):

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

Как только указанная выше директива объявлена, ее можно использовать так:

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

Как и в решении, предложенном @Valentyn Shybanov, нам нужно использоватьng-trim директива, если мы хотим запретить пробелы в начале / конце ввода.

Преимущество этого подхода в 2 раза:

Неверное значение не распространяется на модельИспользуя директиву, легко добавить эту пользовательскую проверку к любому входу, не дублируя наблюдателей снова и снова.
@GStomodelCtrl это контроллер, требуемый директивой. ()require 'ngModel' Nate-Wilkins
Курсор переходит в конец текстового поля каждый раз, когда вы вводите недопустимый символ, попробуйте написать 'Мир' и изменить его наПривет, мир'! Hafez Divandari
Это действительно круто! Работал на меня. Спасибо Vignesh PT
@Dofs Входное значение передается при изменении значения модели - см.github.com/angular/angular.js/blob/master/src/ng/directive/... Nate-Wilkins
0

возможно, стоитng-model на один уровень вверх как часть пользовательского класса со своими собственными методами проверки.

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>

код

(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

Вы можете попробовать это

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

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

});
28

ии:http://plnkr.co/edit/Mb0uRyIIv1eK8nTg3Qng?p=preview

Единственная интересная проблема связана с пробелами: в AngularJS 1.0.3 ng-модель на входе автоматически обрезает строку, поэтому она не обнаруживает, что модель была изменена, если вы добавляете пробелы в конце или в начале (поэтому пробелы не удаляются автоматически код). Но в 1.1.1 есть 'нг-салон» директива, которая позволяет отключить эту функцию (совершить). Так что я'Мы решили использовать 1.1.1 для достижения точных функций, которые вы описали в своем вопросе.

Это было именно то, что я искал. Оказывается, ям уже использую angularjs 1.1.1 Andrew WC Brown
Переназначение переменной области изнутри$watch заставляет слушателя быть снова вызванным. В простых случаях (когда ваш фильтр идемпотентен) вы получите фильтр, выполняющийся дважды при каждой модификации. incarnate
@Valentyn, ваше решение относится к такому вопросу, на который я ссылался в комментарии выше. Благодарю.stackoverflow.com/questions/12176925/... Mark Rajcok
Это решение может иметь плохие побочные эффекты, см. другой ответ ниже, вы должны использовать директиву для этого pilavdzice
3

У меня была похожая проблема и я использовал

ng-change="handler(objectInScope)" 

в моем обработчике я вызываю метод objectInScope для корректного изменения себя (грубый ввод). В контроллере я где-то инициировал, что

$scope.objectInScope = myObject; 

Я знаю, что это нене использовать какие-либо модные фильтры или наблюдатели ... но этоВсе просто и прекрасно работает. Единственным недостатком этого является то, что objectInScope отправляется в вызове обработчику ...

Похожие вопросы