Angular5自定义表单控件转化为formControl

Angular5 Custom Form Control Into formControl

我有这个

HTML

<div [formGroup]="frmStepTwo" fxLayout="column">
    <sfc-account-selector formControlName="account">
    </sfc-account-selector>
</div>

TS(查看)

 this.frmStepTwo = this._formBuilder.group({
        procedure: ["", Validators.required],
        account: ["", Validators.required]
 });

sfc-账户-selector.html

<div class="sfc-account-selector" [formGroup]="ctrlGroup">
    <mat-radio-group
            fxLayout="column"
            (change)="inputChange($event)"
            formControlName="account">
        <mat-radio-button [value]="account" *ngFor="let account of accounts">
            <div>
                <img class="sfc-as-option-icon" [src]="imgBase + account.iconPath"/>
                <div class="sfc-as-label">
                    <span class="sfc-as-name">{{account.serviceName}}</span>
                    <span class="sfc-as-desc">{{account.serviceDescription}}</span>
                </div>
            </div>
        </mat-radio-button>
    </mat-radio-group>

    <small *ngIf="required">REQUIRED</small>
</div>

sfc-account-selector 是自定义表单控件。 我面临的问题是,如果我在 <sfc-account-selector> 上使用 必需属性 ,则 getter 和 setter 将触发。 如果我将我的控件包装在另一个表单控件中,则不会触发要求。

Is there a way to update the "required" when wrapping in a required formControl?

有点棘手。但是我通过这样做让它工作了。

自定义-comp.component.ts

    const isParentControlRequired = function (control: FormControl) {
        if (control.validator !== null) {
            const validator = control.validator({}as AbstractControl);
            return validator && validator.required;
        }
        return false;
    };

    export class someComponent {
          ....

        @Input()
        get required() {
            return this._required;
        }

       set required(req) {
           this._required = coerceBooleanProperty(req);
           this._updateValidators();
           //Emit stateChange to update value in mat-groupCtrl-field
          this.stateChanges.next();
       }

       @Input()
       get disabled() {
           return this._disabled;
       }

       set disabled(dis) {
           this._disabled = coerceBooleanProperty(dis);
           this._disabled ? this.parts.disable() : this.parts.enable();
           this._updateValidators();
           //Emit stateChange to update value in mat-groupCtrl-field
           this.stateChanges.next();
       }

       @Input() formControlName: string;

       private _containerControl: FormControl;

       constructor(private _elRef: ElementRef,
                private _formBuilder: FormBuilder,
                private _focusMonitor: FocusMonitor,
                @Optional() @Host() @SkipSelf()
                private controlContainer: ControlContainer) {

                    this.parts = _formBuilder.group({
                       "pwd": ["", this._baseValidators],
                       "pwdRepeat": ["", this._baseValidators],
                 },
                 {validator: valuesMatchValidation(["pwd", "pwdRepeat"])}
                );

                _focusMonitor.monitor(_elRef.nativeElement, true)
                       .subscribe(origin => {
                            this.focused = !!origin;
                            this.stateChanges.next();
                });
         }


         ngOnInit(): void {

               if (!!this.formControlName && this.controlContainer) {
                     this._containerControl = <FormControl>this.controlContainer.control.get(this.formControlName);
                     this.required = isParentControlRequired(this._containerControl);
        }


        ngDoCheck(): void {
              if (!!this._containerControl) {
                    let parentCtrlDisabled = this._containerControl.disabled;

              if (this.disabled !== parentCtrlDisabled) {
                    this.disabled = parentCtrlDisabled;
              }

             let parentCtrlRequired = isParentControlRequired(this._containerControl) && !parentCtrlDisabled;

            if (this.required !== parentCtrlRequired) {
                 this.required = parentCtrlRequired;
            }
    }

}