انگولار - گروه FormBuilder با اعتبارسنج قدیمی شده است


من همان مشکل را دارم همانطور که در اینجا:

چگونه خطایی که هنگام استفاده از نحو Validator سفارشی با آن مواجه میشوم را رفع کنم؟

گروه FormBuilder منسوخ شده است

من آن سوالات را خواندهام، اما مشکل همچنان در لینتر رخ میدهد:

گروه منسوخ شده است: این API نوعبندی ایمن ندارد و میتواند منجر به مشکلاتی در تغییر نام توسط کامپایلر Closure شود. به جای آن از overload FormBuilder#group با AbstractControlOptions استفاده کنید. توجه داشته باشید که AbstractControlOptions انتظار دارد validators و asyncValidators اعتبارسنجهای معتبر باشند. اگر اعتبارسنجهای سفارشی دارید، مطمئن شوید که پارامتر تابع اعتبارسنجی آنها AbstractControl باشد و نه یک زیرکلاس، مانند FormGroup. این توابع با یک شیء از نوع AbstractControl فراخوانی میشوند و نمیتوان آن را به طور خودکار به یک زیرکلاس تبدیل کرد، بنابراین TypeScript این را به عنوان یک خطا میبیند. برای مثال، امضا (group: FormGroup) => ValidationErrors|null را به (group: AbstractControl) => ValidationErrors|null تغییر دهید. (منسوخ شده)

و اینجا formBuilder من است:

registerForm = this._fb.group({
        firstname: ["", [Validators.required]],
        lastname: ["", [Validators.required]],
        email: ["", [Validators.required, Validators.email]],
        password: ["", [PasswordValidator.strength]],
        confirmPassword: ["", [Validators.required]]
    }, {
        validator: PasswordValidator.confirmed("password", "confirmPassword")
    });

و اعتبارسنج من:

export class PasswordValidator {
    static confirmed = (controlName: string, matchingControlName: string) => {
        return (formGroup: FormGroup) => {
            const control = formGroup.controls[controlName];
            const matchingControl = formGroup.controls[matchingControlName];

            if (matchingControl.errors && !matchingControl.errors.confirmedValidator) {
                return null;
            }

            if (control.value !== matchingControl.value) {
                matchingControl.setErrors({ confirmedValidator: true });
                return ({ confirmedValidator: true });
            } else {
                matchingControl.setErrors(null);
                return null;
            }
        };
    }
}

ظاهراً به چه دلیل؟ من شیء مناسب را برمیگردانم. :/

پاسخ شماره ۱

@OwenKelvin تا حدی درست میگفت. باید به جای validator در formBuilder از validators استفاده شود، حتی اگر فقط یک validator باشد، باز هم متاسفم Owen.

اما مشکل دوم در اعتبارسنج بود. این تابع باید AbstractControl را دریافت کند نه FormGroup. بنابراین کد زیر درست است:

export class PasswordValidator {
    static confirmed = (controlName: string, matchingControlName: string) => {
        return (control: AbstractControl): ValidationErrors | null => {
            const input = control.get(controlName);
            const matchingInput = control.get(matchingControlName);

            if (input === null || matchingInput === null) {
                return null;
            }

            if (matchingInput?.errors && !matchingInput.errors.confirmedValidator) {
                return null;
            }

            if (input.value !== matchingInput.value) {
                matchingInput.setErrors({ confirmedValidator: true });
                return ({ confirmedValidator: true });
            } else {
                matchingInput.setErrors(null);
                return null;
            }
        };
    }
}

پاسخ شماره ۲

هیچکدام از پاسخهای پیشنهادی، حتی در راهحلهای پیوند شده، برای من کار نکرد... اینطور برای من جواب داد:

اینگونه اعتبارسنجها، از جمله اعتبارسنج سفارشی، فراخوانی میشوند:

 this.form = this.fb.group(
      {
      Password:                  ['', { validators:[ Validators.required, Validators.minLength(4)]}],
      ConfirmPassword:           ['', { validators:[ Validators.required, Validators.minLength(4)]}]
      },
      {validators: this.matchingPasswords('Password', 'ConfirmPassword')}
    )

و این همان اعتبارسنج نامیده شده است (در این حالت در همان مؤلفه قرار گرفته است)

matchingPasswords(Password: string, ConfirmPassword: string) {
    return (controls: AbstractControl) => {
      if (controls) {
        const Password = controls.get('Password')!.value;
        const ConfirmPassword = controls.get('ConfirmPassword')!.value;
        //console.log ("check what is passed to the validator", password, confirmPassword);
        if (Password !== ConfirmPassword) { 
          //this is an error set for a specific control which you can use in a mat-error
          controls.get('ConfirmPassword')?.setErrors({not_the_same: true});  
          //this is the returned error for the form normally used to disable a submit button
          return {mismatchedPassword: true}  
        }
      }
      return null;
    }
  }

   
  • نیازی نیست (همانطور که در بعضی از مباحث خواندهام) که تابع اعتبارسنجی در یک ماژول جداگانه باشد
  • نیازی به اعلام فراخوانی اعتبارسنج به صورت «as AbstractControlOptions» نیست. (که در غیر این صورت مانع از کارکرد آن میشد)

قابل توجه:

  1. این فراخوان برای اعتبارسنجها است نه اعتبارسنج
  2. مقدارها از طریق .get استخراج میشوند و نیاز به ! دارند تا مطمئن شویم که null نیستند
  3. اعتبارسنج باید یک ValidationError یا null بازگرداند