4

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() {
  }
}
1
  • 1
    You might want to read up on ControlValueAccessor.. Commented Aug 10, 2020 at 18:06

1 Answer 1

6

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

Sign up to request clarification or add additional context in comments.

2 Comments

I followed your example and I have the formControlDirective which still remains to undefined
make sure that you are importing ReactiveFormsModule

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.