ngxd icon indicating copy to clipboard operation
ngxd copied to clipboard

ControlValueAccessor

Open AndreyKotofotoff opened this issue 6 years ago • 3 comments

When? ))

AndreyKotofotoff avatar May 18 '18 12:05 AndreyKotofotoff

Hello, I implemented a workaround to have this feature implemented and have dynamic forms created at run time by using reactive forms. I pass the formControl in the context and set inside the dynamic component on the input.

// parent form
  <ng-container
    *ngxComponentOutlet="component; context: {formControl: myFormControl};">
  </ng-container>
// dynamic component
<app-my-dynamic-component [formControl]="formControl"></alc-my-dynamic-component>

tiberiuzuld avatar Jul 22 '19 20:07 tiberiuzuld

Dynamic CVA can be achieved this way:

@Component({
  selector: 'cva-adapter',
  template: `
    <ng-container
      [ngxComponentOutlet]="component"
      (ngxComponentOutletActivate)="bind($event)"
    ></ng-container>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: cvaProviders(CvaAdapterComponent)
})
export class CvaAdapterComponent implements ControlValueAccessor, Validators, OnDestroy {
  @Input() public component: any;
 
  public childInstance: ControlValueAccessor<any>;
  public onChange: (_: any) => void;
  public onTouched: (_: any) => void;
  public value: BehaviorSubject<any> = new BehaviorSubject<any>(null);
 
  public registerOnChange(fn: any): void {
    this.onChange = fn;
  }
 
  public registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }
 
  public writeValue(obj: any): void {
    this.value.next(obj);
  }
 
  public validate(): ValidationErrors | null {
    return this.childInstance ? this.childInstance.validate() : null;
  }
 
  public setDisabledState(isDisabled: boolean): void {
    if (this.childInstance?.setDisabledState) {
      this.childInstance.setDisabledState(isDisabled);
    }
  }
 
  public bind(childInstance: ControlValueAccessor<any>) {
    this.childInstance = childInstance;
    this.childInstance.registerOnChange(this.onChange);
    this.childInstance.registerOnTouched(this.onTouched);
    this.value.pipe(
      takeUntil() // Don't forget to unsubscribe
    ).subscribe(value => {
      this.childInstance.writeValue(value);
    });
  }
 
  ngOnDestroy(): void {
    this.childInstance = undefined;
  }
}

ambeur avatar Oct 13 '20 09:10 ambeur

Hey @zvnt! I have working example with dynamic forms here https://stackblitz.com/edit/angular-form-builder-lcsabo?file=src%2Fapp%2Fdynamic-field%2Fdynamic-field.component.ts

AutoCVA is @thekiba `s approach to reduce cva interface boilerplate

alQlagin avatar Oct 13 '20 09:10 alQlagin