programing

Angular의 사용자 정의 양식 구성요소에서 FormControl에 액세스합니다.

javamemo 2023. 10. 22. 19:22
반응형

Angular의 사용자 정의 양식 구성요소에서 FormControl에 액세스합니다.

Angular 애플리케이션에 사용자 지정 양식 제어 구성 요소가 있으며, 이 구성 요소는 다음을 구현합니다.ControlValueAccessor인터페이스.

그러나, 나는 접속하고 싶습니다.FormControl예를 들어, 내 구성 요소와 연관되어 있습니다.반응식을 사용하고 있습니다.FormBuilder를 사용하여 폼 제어를 제공합니다.formControlName기여하다.

그럼 어떻게 접속해야 합니까?FormControl사용자 정의 양식 구성 요소 내부의 인스턴스?

이 해결책은 Angular 저장소에서의 논의에서 탄생했습니다.이 문제에 관심이 있으시면 꼭 읽어보시거나 참여해 주시기 바랍니다.


제가 연구해봤습니다.FormControlName다음과 같은 해결책을 쓰도록 영감을 받았습니다.

@Component({
  selector: 'my-custom-form-component',
  templateUrl: './custom-form-component.html',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: CustomFormComponent,
    multi: true
  }]
})
export class CustomFormComponent implements ControlValueAccessor, OnInit {

  @Input() formControlName: string;

  private control: AbstractControl;


  constructor (
    @Optional() @Host() @SkipSelf()
    private controlContainer: ControlContainer
  ) {
  }


  ngOnInit () {

    if (this.controlContainer) {
      if (this.formControlName) {
        this.control = this.controlContainer.control.get(this.formControlName);
      } else {
        console.warn('Missing FormControlName directive from host element of the component');
      }
    } else {
      console.warn('Can\'t find parent FormGroup directive');
    }

  }

}

부모님께 주사를 놓는 겁니다FormGroup구성 요소에 연결한 다음 특정 정보를 얻음FormControl를 통해 얻은 제어 이름을 사용하여 그것으로부터.formControlName구속력이 있는

단, 이 솔루션은 다음과 같은 경우에 사용할 수 있도록 특별히 조정되어 있습니다.FormControlName지시는 호스트 요소에서 사용됩니다.다른 경우에는 효과가 없을 겁니다.이를 위해서는 몇 가지 논리를 추가해야 합니다.Angular가 이 문제를 다루어야 한다고 생각한다면 반드시 토론에 참석해야 합니다.

사용.formControlName입력 매개 변수가 를 통해 바인딩될 때 작동하지 않기 때문에[formControl]지시의

여기에 입력 매개변수 없이 양방향으로 작동하는 솔루션이 있습니다.

export class MyComponent implements AfterViewInit {

  private control: FormControl;

  constructor(
    private injector: Injector,
  ) { }

  // The form control is only set after initialization
  ngAfterViewInit(): void {
    const ngControl: NgControl = this.injector.get(NgControl, null);
    if (ngControl) {
      this.control = ngControl.control as FormControl;
    } else {
      // Component is missing form control binding
    }
  }
}

댓글에서 찾은 이전 답변과 문서를 바탕으로, 여기에 제 의견이 가장 깨끗한 해결책입니다.ControlValueAccessor기본 성분.

// No FormControl is passed as input to MyComponent
<my-component formControlName="myField"></my-component>
export class MyComponent implements AfterViewInit, ControlValueAccessor  {

  constructor(@Optional() @Self() public ngControl: NgControl) {
    if (ngControl != null) {
      // Setting the value accessor directly (instead of using
      // the providers) to avoid running into a circular import.
      ngControl.valueAccessor = this;
    }
  }

    ngAfterContentInit(): void {
       const control = this.ngControl && this.ngControl.control;
       if (control) {
          // FormControl should be available here
       }
    }
}

이 솔루션을 사용하면 CI 순환 종속성이 발생하므로 구성 요소에 NG_VALUE_ACCESCOR 공급자를 지정할 필요가 없습니다.생성자가 Accessor 값을 올바르게 설정합니다.

@Ritesh가 이미 코멘트에 작성한 것처럼 폼 제어를 입력 바인딩으로 전달할 수 있습니다.

<my-custom-form-component [control]="myForm.get('myField')" formControlName="myField">
</my-custom-form-component>

그런 다음 사용자 정의 폼 구성 요소 내부에 폼 제어 인스턴스를 가져올 수 있습니다.

@Input() control: FormControl;

다음은 FormControlName 및 FormControl 입력에 모두 적용되는 승인된 답변의 단순화/정리 버전입니다.

export class CustomFormComponent implements ControlValueAccessor, OnInit {

  @Input() formControl: FormControl;

  @Input() formControlName: string;

  // get ahold of FormControl instance no matter formControl or formControlName is given.
  // If formControlName is given, then controlContainer.control is the parent FormGroup/FormArray instance.
  get control() {
    return this.formControl || this.controlContainer.control.get(this.formControlName);
  }

  constructor(private controlContainer: ControlContainer) { }
}

언급URL : https://stackoverflow.com/questions/44731894/get-access-to-formcontrol-from-the-custom-form-component-in-angular

반응형