मेरे पास सरल इनपुट के साथ 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
David 1 मार्च 2020, 16:41
क्या आप अपना वर्तमान कोड पोस्ट कर सकते हैं
 – 
Kurt Hamilton
1 मार्च 2020, 17:05
हेयर यू गो। टिप्पणी किए गए भाग वे भाग हैं जिन पर मैं काम करना चाहता हूं
 – 
David
1 मार्च 2020, 17:17

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

1
Kurt Hamilton 5 मार्च 2020, 11:26
यदि मैं रनटाइम के दौरान नियंत्रण जोड़/हटा दूं तो क्या होगा?
 – 
David
5 मार्च 2020, 11:09
अपने मॉडल की तरह ही प्रपत्र सरणी को प्रबंधित करने के अलावा, आपको प्रभावित अनुक्रमणिकाओं पर प्रभावित नियंत्रणों को संशोधित करने की आवश्यकता होगी। मैंने अपने स्टैकब्लिट्ज को यह दिखाने के लिए फोर्क किया है कि मैं अलग-अलग आइटम कैसे हटाऊंगा। stackblitz.com/edit/angular-f93sgn
 – 
Kurt Hamilton
5 मार्च 2020, 11:21
नोट: setValidators का उपयोग करने से सभी मौजूदा सत्यापनकर्ता अधिलेखित हो जाएंगे। इसलिए यदि आप अतिरिक्त सत्यापनकर्ताओं का उपयोग कर रहे हैं, तो उन्हें भी शामिल करने की आवश्यकता होगी
 – 
Kurt Hamilton
5 मार्च 2020, 11:22
मैंने थोड़ा और विवरण शामिल करने के लिए अपना उत्तर संपादित कर लिया है
 – 
Kurt Hamilton
5 मार्च 2020, 11:26

फ़ंक्शन में बस जोड़ें और तर्क दें 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] में यदि कोई नियंत्रण अमान्य है तो आपके पास है

आप इस स्टैकब्लिट्ज

नोट: मैं सीधे फॉर्मकंट्रोल के फॉर्मएरे का उपयोग करता हूं, लेकिन यह वही है

कर्ट के उत्तर को पढ़ने के बाद अपेट, वास्तव में यह आवश्यक नहीं है बाइंड (यह) वैलिडेटर में, कर्ट के अनुसार पिछले नियंत्रण को सरल पास करें।

0
Eliseo 1 मार्च 2020, 18:58
यह वास्तव में फॉर्मएरे के लिए सत्यापनकर्ता को बाध्य करने और फिर बच्चों की वैधता निर्धारित करने का एक दिलचस्प विचार है
 – 
David
5 मार्च 2020, 11:10