Search code examples
angularformsangular7angular-reactive-formsangular-forms

Use custom select component in Reactive form using Angular 7


I am not getting value on click of Submit button. Below is what I tried so far.

custom component HTML-

<div class="form-group custom-input-overlap">
  <select class="form-control custom-select" (change)="change($event)" [ngClass]="{'filledTxt': selectedItem.length > 0}">
    <option value="" selected disabled>{{labelStr}}</option>
    <option *ngFor="let item of titleData" [value]="item.lovId.lovId" [selected]="item.lovId.lovId == selectedItem" >{{ item.lovValue }}</option>
  </select>
  <label for="labelStr" style="left:25px;">{{labelStr}}</label>
</div>

custom component TS file

import { Component, ChangeDetectionStrategy, ChangeDetectorRef, Input, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
  selector: 'app-custom-select',
  templateUrl: './custom-select.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [
    { 
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomSelectComponent),
      multi: true
    }
  ]
})
export class CustomSelectComponent implements ControlValueAccessor {

  selectedItems = [];
  @Input() labelStr:string;
  @Input() groupID:string;
  @Input() selectedItem:string;

  private propagateOnChange = (value: {lovId, lovValue}[]) => {};
  private propagateTouched = (value: {lovId, lovValue}[]) => {};


  titleData = [
      {
          "lovId":{"lang":"EN","lovId":"1"},
          "lovValue":"Mr"
      },
      { 
          "lovId":{"lang":"EN","lovId":"2"},
          "lovValue":"Mrs"
      },
      {
          "lovId":{"lang":"EN","lovId":"3"},
          "lovValue":"Dr"
      },
      {
          "lovId":{"lang":"EN","lovId":"5"},
          "lovValue":"Miss"
      }
  ]

  constructor(
    private cdRef: ChangeDetectorRef
  ) { 
      console.log("seletced Item = "+this.selectedItem+" groupID = "+this.groupID)
  }

  writeValue(items: {lovId, lovValue}[]) {
    this.selectedItems = items;
  }

  registerOnChange(fn) {
    this.propagateOnChange = fn;
  }

  registerOnTouched(fn) {
    this.propagateTouched = fn;
  }

  change(e) {
    this.selectedItem = e.target.options[e.target.options.selectedIndex].value;
    console.log("selected Item = "+this.selectedItem)
  }
}

Component used in Reactive Form

<form [formGroup]="ccnForm" (ngSubmit)="onSubmit()">
        <div class="row">
            <div class="col-md-5 offset-md-1">
                <app-custom-select formControlName="projectType" labelStr="Project type" groupID="CM_GENDER" selectedItem="3" ></app-custom-select>
            </div>

        </div>
    </form>

Reactive form TS file

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

@Component({   selector: 'app-ccn-request',   templateUrl: './ccn-request.component.html',   styleUrls: ['./ccn-request.component.css'] }) export class CcnRequestComponent {

     ccnForm: FormGroup;

  constructor(
    private fb: FormBuilder   ) {
    this.ccnForm = this.fb.group({
      projectType: ['', (c: AbstractControl) => {
        return c.value && c.value.length && c.value.length > 1 ? null : { test: true }
      }]
    });

    this.ccnForm.valueChanges.subscribe(console.log);   }

  get ccnFormControl(){ return this.ccnForm.controls; }

  onSubmit(){
      console.log("Project Name = "+this.ccnFormControl.projectType.value)   }
   }

How can I get the value of custom component value on Submit button in Angular Reactive Form?


Solution

  • In your child component

    change(e) {
        this.selectedItem = e.target.options[e.target.options.selectedIndex].value;
        console.log("selected Item = "+this.selectedItem)
        this.propagateOnChange({selectedItem: this.selectedItem});
      }
    

    In your parent just ngOnInit just subscribe to your form

     this.ccnForm.controls.projectType.valueChanges
                .subscribe(selectedItem => {        
                   // Do something here with your selected item
                    this.selectedItem = selectedItem;
                });