입력의 ng-model에 대한 필터 텍스트 입력이 있고 사용자가 공백을 사용하는

텍스트 입력이 있고 사용자가 공백을 사용하는 것을 원하지 않으며 입력 한 모든 내용이 소문자로 바뀝니다.

예를 들어 ng-model에서 필터를 사용할 수 없다는 것을 알고 있습니다.

ng-model='tags | lowercase | no_spaces'

나는 내 자신의 지시문을 만드는 것을 보았지만 입력에 함수를 추가 $parsers하고 $formatters업데이트하지 않았으며 ng-model그것에있는 다른 요소 만 업데이트 했습니다.

현재 입력중인 입력을 어떻게 변경할 수 있습니까?

저는 본질적으로 여기 StackOverflow의 것과 똑같이 작동하는 ‘태그’기능을 만들려고합니다.



답변

모델 값을보고 변경시 업데이트하는 것이 좋습니다. http://plnkr.co/edit/Mb0uRyIIv1eK8nTg3Qng?p=preview

유일한 흥미로운 문제는 공백입니다. 입력시 AngularJS 1.0.3 ng-model에서 자동으로 문자열을 트리밍하므로 끝이나 시작에 공백을 추가하면 모델이 변경되었음을 감지하지 못합니다 (따라서 공백은 자동으로 제거되지 않습니다. 암호). 그러나 1.1.1에는이 기능을 비활성화 할 수있는 ‘ng-trim’지시문이 있습니다 ( commit ). 따라서 질문에서 설명한 정확한 기능을 얻기 위해 1.1.1을 사용하기로 결정했습니다.


답변

AngularJS 입력과 ngModeldirecive 의 의도는 유효하지 않은 입력이 모델에서 끝나서는 안된다는 것입니다 . 모델은 항상 유효해야합니다. 잘못된 모델을 갖는 문제는 잘못된 모델을 기반으로 (부적절한) 조치를 취하고 실행하는 감시자가있을 수 있다는 것입니다.

내가보기에 적절한 해결책은 $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 배입니다.

  • 잘못된 값은 모델에 전파되지 않습니다.
  • 지시어를 사용하면 감시자를 반복해서 복제하지 않고도 입력에이 사용자 지정 유효성 검사를 쉽게 추가 할 수 있습니다.

답변

이 문제에 대한 해결책은 컨트롤러 측에 필터를 적용하는 것입니다.

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

$filter종속성 으로 선언하는 것을 잊지 마십시오 .


답변

읽기 전용 입력 필드를 사용하는 경우 필터와 함께 ng-value를 사용할 수 있습니다.

예를 들면 :

ng-value="price | number:8"


답변

$ formatters 및 $ parsers 컬렉션 모두에 추가하는 지시문을 사용하여 변환이 양방향으로 수행되도록합니다.

jsfiddle에 대한 링크를 포함하여 자세한 내용 은 이 다른 답변 을 참조하십시오.


답변

비슷한 문제가 있었고

ng-change="handler(objectInScope)" 

내 처리기에서 objectInScope의 메서드를 호출하여 자신을 올바르게 수정합니다 (거친 입력). 컨트롤러에서 나는 어딘가에서 시작했습니다.

$scope.objectInScope = myObject; 

나는 이것이 어떤 멋진 필터 나 감시자를 사용하지 않는다는 것을 알고있다. 그러나 그것은 간단하고 훌륭하게 작동한다. 이것의 유일한 단점은 objectInScope가 핸들러에 대한 호출로 전송된다는 것입니다.


답변

복잡한 비동기 입력 유효성 검사를 수행하는 경우 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) })
  };

})();