Mohamed Rafiq P
Mohamed Rafiq P

Reputation: 790

How to build reusable field for reactive form in Angular

I am trying to build a reusable field component for reactive form but I am unable to get a value from custom-input component.

<form [formGroup]="form" (ngSubmit)="submit()">
  <custom-input id="name" name="name" formControlName="name"></custom-input>
  <button type="submit" name="button">Submit</button>
</form>

My custom input reusable componeent

import { Component, OnInit, Input } from '@angular/core';
import { FormControl } from "@angular/forms";

@Component({
  selector: 'custom-input',
  template: '<input type="text" [class]="class" [id]="id" [name]="name" [formControlName]="formControlName">',
  styles: []
})
export class CustomInputComponent implements OnInit {
  @Input() public id: string;
  @Input() public class: string;
  @Input() public name: string;
  @Input() public formControlName: string;

  constructor() { }

  ngOnInit() {
  }
}

Upvotes: 4

Views: 3546

Answers (1)

mmihalcea
mmihalcea

Reputation: 76

You can implement ControlValueAccessor, but might not want to re-implement the methods for the native input. In order to do that, you can use the FormControlDirective to get access to valueAccessor.

formControl and formControlName are added as input properties, so it will work in both cases. If formControlName is provided, the instance of FormControl will be retrieved from the ControlContainer.

@Component({
      selector: 'app-custom-input',
      template: `<input type="text" [formControl]="control">`,
      styleUrls: ['./custom-input.component.scss'],
      providers: [
        {
          provide: NG_VALUE_ACCESSOR,
          useExisting: CustomInputComponent,
          multi: true
        }
      ]
    })
    export class CustomInputComponent implements ControlValueAccessor {
      @Input() formControl: FormControl;
      @Input() formControlName: string;
    
      @ViewChild(FormControlDirective, {static: true})
      formControlDirective: FormControlDirective;
      private value: string;
      private disabled: boolean;
    
      constructor(private controlContainer: ControlContainer) {
      }
    
      get control() {
        return this.formControl || this.controlContainer.control.get(this.formControlName);
      }
    
    
      registerOnTouched(fn: any): void {
        this.formControlDirective.valueAccessor.registerOnTouched(fn);
      }
    
      registerOnChange(fn: any): void {
        this.formControlDirective.valueAccessor.registerOnChange(fn);
      }
    
      writeValue(obj: any): void {
        this.formControlDirective.valueAccessor.writeValue(obj);
      }
    }

Source: https://medium.com/angular-in-depth/dont-reinvent-the-wheel-when-implementing-controlvalueaccessor-a0ed4ad0fafd

Upvotes: 6

Related Questions