커스텀 디렉티브에 Angular Validation 디렉티브를 프로그래밍 방식으로 적용할 수 있습니까?
html 입력에는 다음과 같은 패턴이 많이 있습니다.이것은 전화번호입니다.
<input type="text" ng-model="CellPhoneNumber" required ng-pattern="/^[0-9]+$/" ng-minlength="10" />
적용되는 위치에 따라 Angular에게 다음 세 가지 규칙을 모두 적용하도록 지시하는 커스텀 디렉티브를 만들고 싶습니다.
<input type="text" ng-model="CellPhoneNumber" bk-ng-validation="phoneNumber"/>
그런 다음, 내 지시어의 코드가 다음 함수를 찾아 호출합니다.phoneNumber
예를 들어 다음과 같은 것을 보고 싶습니다.
리스트 1:
function bkNgPhoneNumber(model) {
// This is purely SPECULATIVE pseudo-code, just to convey an idea.
model.errors.add(applyMinLength(10, model));
model.errors.add(applyMaxLength(15, model));
model.errors.add(applyPattern("/^[0-9]+$/", model));
}
이러한 규칙에 대한 코드 재작성보다 위의 접근 방식을 선호합니다. 예를 들어 다음과 같습니다.
리스트 2:
function phoneNumber(model) {
if (model.length < 10 || model.length > 15) {
model.errors.add("Must be 10 to 15 chars!");
}
}
모든 속성 기반 지시어를 없애고 싶지는 않지만 목록 1 코드를 호출하는 '매크로' 지시어를 만드는 것이 좋습니다. 이 명령어는 일련의 더 많은 '마이크로' 유효성 검사를 인턴으로 호출합니다.
이를 위한 한 가지 방법(즉, 코드를 다시 작성하지 않고 기존 검증자를 적용)은 검증 지침의 각 속성을 추가하고 재컴파일을 강제하는 것이다.이를 위해서는 지시가 높은 우선 순위를 가져야 하며, 또한terminal: true
.
app.directive("bkNgValidation", function($compile){
return {
priority: 10000,
terminal: true,
link: function(scope, element){
element.attr("ng-required", "true");
element.attr("ng-minlength", 20);
element.attr("ng-maxlength", 30);
// prevent infinite loop
element.removeAttr("bk-ng-validation");
$compile(element)(scope);
}
};
});
더 많은 검증을 사용하는 경우 제한 없이 요소를 식별하고 검증하는 서비스를 생성할 수 있습니다.angular의 기본 지시어는 그대로입니다.
예를 들어:
module.service('$Validation', ["$compile",function($compile){
this.validators = {
'phoneNumber': [['required', 1], ['minlength',6], ['maxlength', 10], ['pattern', /^[0-9]+$/.source]],
'phoneNumber2Custom': function(value){
return /^[0-9]{6,10}$/.test(value)
},
'userTwitter': function(value){
return /^@(.+)/.test(value)
}
// ...etc... /
}
this.add = function(scope, element, attrs, model){
var name = attrs.bkNgValidation, type;
if(!(type = this.validators[name])) return;
else if(angular.isFunction(type)) return (model.$validators[name] = type);
element.removeAttr("bk-ng-validation");
angular.forEach(type, function(expr){
element.attr(expr[0], expr[1])
});
$compile(element)(scope)
};
}]).directive('bkNgValidation', ["$Validation", function ($Validation) {
return {
require: '?ngModel',
priority: 1e5,
link: function(){
$Validation.add.apply($Validation, arguments);
}
}
}])
다음과 같은 방법을 사용할 수 있습니다.
.directive('bkNgValidation', function () {
return: {
link: function (scope, element, attrs) {
if (attrs['bk-ng-validation'] === 'phoneNumber') {
element.$validateModel(function (value, validator) {
if (value.length < 10 || value.length > 15) {
validator.$setValidity('phone', true);
} else {
validator.$setValidity('phone', false);
}
});
}
}
}
})
필요한 모든 검증자를 통한 제어를 포함하는 새 구성 요소를 생성할 수 있습니다.구성 요소는 다음과 같습니다.
<my-control name="field" ng-model="text"></my-control>
필요한 논리 컴포넌트는 모두 내부에 보관해야 합니다.그러기 위해서는my-control
directive를 지정합니다.템플릿 내부에는 다음과 같은 검증 속성을 가진 입력을 배치할 수 있습니다.
<input type="text" ng-model="value" class="form-control" ng-pattern="'^(?!ng-*)'" minlength="3">
그런 다음 컴포넌트에서 ng-model 값을 바인드하여 다음과 같이 입력해야 합니다.
angular.module('app', []).directive('myControl', function() {
return {
restrict: 'E',
require: 'ngModel', //import ngModel into linking function
templateUrl: 'myControl.tpl',
scope: {}, //our component can have private properties, isolate it
link: function(scope, elm, attrs, ngModel) {
// reflect model changes via js
ngModel.$render = function() {
scope.value = ngModel.$viewValue;
};
// update model value after changes in input
scope.$watch('value', function(value) {
ngModel.$setViewValue(value);
});
}
};
});
다음은 이 컴포넌트의 동작과 작동 방식을 보여 주는 데모입니다.
지시문은 유지하기가 그만큼 힘들다고 가정하고 요소에 따라 필요한 모든 검증을 제공하기 위해 지시문을 유지하려고 하기 때문에 반대 방향으로 가고 있습니다.
흥미로운 접근법이긴 하지만 이 접근법의 모듈화에 대해 주의를 기울여야 합니다. 즉, 이 많은 노력을 하나의 지침에만 할당하는 것은 "순수한 각도 방식"을 사용하여 작업을 수행하는 모범 사례에 반하는 것입니다.
계속 꼭 권합니다.ngModelController
(각도주입할 수 있는 JS Docs) 속성link()
하나의 지시어의 기능.더 정확히 말하면, '우리'는요.$validators
.
개 요?$validators
NgModel 컨 ng ng ng ng ng ng ng 。
검증 중에 부울을 반환하는 요소에 대한 유효성을 설정/해제할 수 있습니다.
app.directive('validator', function () {
var definition = {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, ngModel) {
// Return if no ngModelController
if (!ngModel) {
return;
}
ngModel.$validators.validateLength = function (modelValue, viewValue) {
// modelValue === the value of the ngModel, on the script side
// viewValue === the value of the ngModel, on the HTML (rendered) side
//
// you can set-up $parsers, $formatters, $validators, etc, to handle the element
return !(modelValue.length > 20);
}
}
};
return definition;
});
이 구현에 대한 자세한 내용을 읽어보시길 권장합니다. 왜냐하면 특정 조작은 다음 동작의 흐름을 방해할 수 있기 때문입니다.$digest
이치노
편집 1:
제가 댓글에 언급했듯이, 여기 작동하는 예를 든 플렁커가 있습니다.
언급URL : https://stackoverflow.com/questions/30149924/can-i-programmatically-apply-angular-validation-directives-inside-a-custom-direc
'programing' 카테고리의 다른 글
Woocommerce 3에서 CRUD 메서드를 사용하여 프로그래밍 방식으로 제품 생성 (0) | 2023.03.23 |
---|---|
$http 요구는 각진 CORS에서 도메인 간 쿠키를 전송하지 않습니다. (0) | 2023.03.23 |
TypeError: HTMLInputElement 인터페이스를 구현하지 않은 개체에서 스텝업이 호출되었습니다. (0) | 2023.03.23 |
AJAX Mailchimp 등록 양식 통합 (0) | 2023.03.23 |
Angular, React 및 Blaze(클라이언트 측 Meteor)의 주요 설계 차이는 무엇입니까? (0) | 2023.03.23 |