텍스트 입력이 있고 사용자가 공백을 사용하는 것을 원하지 않으며 입력 한 모든 내용이 소문자로 바뀝니다.
예를 들어 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 입력과 ngModel
direcive 의 의도는 유효하지 않은 입력이 모델에서 끝나서는 안된다는 것입니다 . 모델은 항상 유효해야합니다. 잘못된 모델을 갖는 문제는 잘못된 모델을 기반으로 (부적절한) 조치를 취하고 실행하는 감시자가있을 수 있다는 것입니다.
내가보기에 적절한 해결책은 $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) })
};
})();