0

I'm trying to create a custom component with an input form control inside but I have no idea how to connect the directive formControl and formControlName to the inner input, this is my code:

<div class="input-group">
    <input class="form-control form-control-sm"
        #code />
    <div class="input-group-append">
        <button type="button" class="btn btn-sm btn-success"
            (click)="search()">
            <i class="fa fa-search"></i>
        </button>
    </div>
</div>

this is the .ts file

import { Input, Component, forwardRef, OnInit, ViewChild } from '@angular/core';
import { DefaultValueAccessor, ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';

@Component({
    selector: 'search-input',
    templateUrl: './search-input.component.html',
    styleUrls: ['./search-input.component.scss'],
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => SearchInputComponent),
            multi: true
        }
    ]
})
export class SearchInputComponent implements OnInit, ControlValueAccessor {
    writeValue(obj: any) {
    }

    registerOnChange(fn: any) {
    //this.valueAccesor.registerOnChange(fn);
    }

   registerOnTouched(fn: any) {
    //this.valueAccesor.registerOnTouched(fn);
   }

    setDisabledState(isDisabled: boolean) {
    //this.valueAccesor.setDisabledState(isDisabled);
    }
}

It should

<search-input formControlName="code">

Or

<search-input formControl="code">

Please, help me with this, I don't have much experience with Angular

1 Answer 1

2

In order to have a child component work with the same parent form, you should pass in the Parent Form instance as an input to the child component. The parent form will use the form builder to create the child form control. The child will define the template for the control.

Here is a parent form (Sandbox) with a child component (AppTestInputForm):

import { Component, OnInit } from '@angular/core';
import { FormBuilder, Form, FormGroup, FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'app-sandbox',
  templateUrl: './sandbox.component.html',
  styleUrls: ['./sandbox.component.css']
})
export class SandboxComponent implements OnInit {
  form: FormGroup;

  constructor(private formBuilder: FormBuilder) { 
    this.form = formBuilder.group({
      searchValue: new FormControl('')
    });
  }
  ngOnInit() {

  }

  submit() {
    if(this.form.valid) {
      console.log(this.form.get('searchValue').value, 'submitting search value');
    }
  }

}
<form [formGroup]="form" (ngSubmit)="submit()">
    <app-test-input-form [parentForm]="form"></app-test-input-form>
    <button type="submit" class="btn btn-primary">Submit</button>
 </form>

Here is the child component which contains the search input:

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

@Component({
  selector: 'app-test-input-form',
  templateUrl: './test-input-form.component.html',
  styleUrls: ['./test-input-form.component.css']
})
export class TestInputFormComponent implements OnInit {
  @Input() parentForm: FormGroup;

  constructor(private formBuilder: FormBuilder) { 

  }

  ngOnInit() {

  }

  search() {
    console.log('searching with value', this.parentForm.get('searchValue').value);
  }
}
<div class="input-group" [formGroup]="parentForm">
  <input class="form-control form-control-sm" formControlName="searchValue" />
  <div class="input-group-append">
    <button type="button" class="btn btn-sm btn-success" (click)="search()">
            <i class="fa fa-search"></i>
        </button>
  </div>
</div>

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

2 Comments

I tried this approach without looking at your post. It works fine with the initial value for the field being empty, but gives me : ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value for 'ng-valid': 'true'. Current value: 'false'.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.