मेरे पास सरल इनपुट के साथ FormArray
है। मैं सत्यापनकर्ता फ़ंक्शन (कस्टम) को FormArray
में इनपुट की एक अनुक्रमणिका पास करना चाहता हूं, क्योंकि मेरा सत्यापनकर्ता उस पर आधारित है। उदाहरण के लिए, मैं चाहता हूं कि प्रत्येक अनुवर्ती AbstractControl
में पहले की तुलना में अधिक अक्षर हों (यह केवल एक उदाहरण है, एक इंडेक्स पास करना वह है जो मुझे वास्तव में प्राप्त करने की आवश्यकता है)।
मेरा मतलब है कि अगर मुझे ऐसा कुछ मिल सकता है
ngOnInit(): void {
this.items = this.items?.length ? this.items : this.getDefaults(this.size)
const inputs: FormArray = this.formGroup.get('inputs') as FormArray
for (let item of this.items) {
inputs.push(this.fb.control(
item.value,
this.validator(),
this.asyncValidator(),
))
}
}
private validator(): ValidatorFn {
return (abstractControl: AbstractControl/*, indexInArray */) => {
// const lenOfPrev = this.items[indexInArray - 1].value.length
if (abstractControl.value.length <= 0 /* lenOfPrev */) {
return {
notLargeEnough: 'should be bigger'
}
}
return null
}
}
2 जवाब
आपका उद्देश्य किसी अन्य नियंत्रण के विरुद्ध नियंत्रण को मान्य करना है। तथ्य यह है कि वे एक फॉर्म ऐरे में हैं, थोड़ा अप्रासंगिक है।
कस्टम सत्यापनकर्ता लिखते समय, आप इसके इंटरफ़ेस से बंधे होते हैं:
interface ValidatorFn {
(control: AbstractControl): ValidationErrors | null
}
इसलिए यदि आप इंटरफ़ेस फ़ंक्शन में किसी अन्य नियंत्रण के संदर्भ को इंजेक्ट नहीं कर सकते हैं, तो आपका एकमात्र अन्य विकल्प अन्य नियंत्रण को फ़ंक्शन में ही इंजेक्ट करना है।
ngOnInit(): void {
this.items = this.items?.length ? this.items : this.getDefaults(this.size)
const inputs: FormArray = this.formGroup.get('inputs') as FormArray
this.items.forEach((item, i) => {
const previousControl = i > 0 ? inputs.controls[i - 1] : null;
inputs.push(this.fb.control(
item.value,
this.validator(),
this.asyncValidator(),
));
});
}
private validator(previousControl: AbstractControl): ValidatorFn {
return (control: AbstractControl) => {
if (!previousControl || control.value.length > previousControl.value.length) {
return null;
}
return {
notLargeEnough: 'should be bigger'
};
}
}
आपको इस तथ्य को संभालना होगा कि पहले नियंत्रण के पास तुलना करने के लिए पिछला नियंत्रण नहीं है।
डेमो: https://stackblitz.com/edit/angular-9atrvn
आप शायद कुछ ऐसा जोड़ना चाहेंगे जो किसी मूल्य में परिवर्तन होने पर संबंधित नियंत्रण पर सत्यापन को अद्यतन करता है, क्योंकि यह डिफ़ॉल्ट रूप से नहीं होता है।
संपादित करें
यदि आपकी सरणी अपने जीवनकाल के दौरान बदलती है, तो आप प्रभावित वस्तुओं के सत्यापनकर्ताओं को अपडेट करने के लिए FormControl.setValidators(validators)
का उपयोग कर सकते हैं।
यदि आप सरणी से शुरू करते हैं
A <- B <- C <- D <- E
और एक को हटा दें:
A <- B <- D <- E
तब केवल निर्भरता जो बदल गई है वह है D -> C
अब D -> B
बन जाती है। इसलिए आपको D
के लिए B
पर निर्भर रहने के लिए सत्यापनकर्ता को अपडेट करना होगा।
नोट: सेट वैलिडेटर का उपयोग करने से सभी मौजूदा सत्यापनकर्ता अधिलेखित हो जाएंगे। इसलिए यदि आप अतिरिक्त सत्यापनकर्ताओं का उपयोग कर रहे हैं, तो उन्हें भी शामिल करने की आवश्यकता होगी।
फोर्कड डेमो: https://stackblitz.com/edit/angular-f93sgn
setValidators
का उपयोग करने से सभी मौजूदा सत्यापनकर्ता अधिलेखित हो जाएंगे। इसलिए यदि आप अतिरिक्त सत्यापनकर्ताओं का उपयोग कर रहे हैं, तो उन्हें भी शामिल करने की आवश्यकता होगी
फ़ंक्शन में बस जोड़ें और तर्क दें Validator
private validator(indexInArray:number): ValidatorFn { //<--here
return (abstractControl: AbstractControl) => {
//you can use indexInArray here
if (indexInArray==0) //For the first give always valid
return null;
//I change this.items by this.form.value
const lenOfPrev = this.form.value[indexInArray - 1].value.length
if (abstractControl.value.length <= lenOfPrev.length) {
return {
notLargeEnough: 'should be bigger'
}
}
return null
}
}
लेकिन, यदि आप घटक के मूल्यों का उपयोग कर रहे हैं तो आपको सत्यापनकर्ता को "बाध्य" करने की आवश्यकता है
this.items.forEach((item, i) => {
const previousControl = i > 0 ? inputs.controls[i - 1] : null;
inputs.push(this.fb.control(
item.value,
this.validator(i).bind(this), //<--see the argument and the "bind"
this.asyncValidator(),
));
});
पर शर्मिंदा। इस दृष्टिकोण में एक प्रासंगिक दोष है, यदि आप बदलते हैं तो क्या होता है, उदा। दूसरा इनपुट 'आआ' से 'आआआ' तक?. यदि आपका तीसरा इनपुट 'bbbb' है, तो पहले मान्य था, लेकिन परिवर्तन के बाद नहीं। लेकिन angualr इस पर ध्यान दे सकता है क्योंकि तीसरा इनपुट नहीं बदलता है। तो, सभी फॉर्मएरे पर एक वैलिडेटर का उपयोग क्यों न करें। एक कस्टम सत्यापनकर्ता के रूप में एक वस्तु लौटाता है, आप वापस आ सकते हैं, उदा। एक सरणी [झूठी, झूठी, सच्ची, झूठी] और इस मूल्य के बारे में पूछें
private validatorArray()
{
return (formArray:FormArray)=>{
if (!formArray.value)
return null;
const result= (formArray.value.map((x:any,i:number)=>{
if (i==0)
return false;
return (x.length<=formArray.value[i-1].length)
}))
return result.find(x=>x)?{error:result}:null;
}
}
form.errors?.error[i]
में यदि कोई नियंत्रण अमान्य है तो आपके पास है
नोट: मैं सीधे फॉर्मकंट्रोल के फॉर्मएरे का उपयोग करता हूं, लेकिन यह वही है
कर्ट के उत्तर को पढ़ने के बाद अपेट, वास्तव में यह आवश्यक नहीं है बाइंड (यह) वैलिडेटर में, कर्ट के अनुसार पिछले नियंत्रण को सरल पास करें।
संबंधित सवाल
नए सवाल
angular
Google से वेब फ्रेमवर्क के बारे में प्रश्न इस टैग का उपयोग कोणीय प्रश्नों के लिए करें जो एक व्यक्तिगत संस्करण के लिए विशिष्ट नहीं हैं। पुराने AngularJS (1.x) वेब ढांचे के लिए, कोणीयज टैग का उपयोग करें।