0

In the following example I have a simple dropdown list which contains list of customers. When you select a customer from the dropdown list, I need followings to be done.

  1. Selected customer name should be shown in the "txtCustomerName" text box.
  2. Selected customer name should be shown in the "spnCustomerId" span element (I have done it in a way and I want to make sure if I'm doing it in a right way with the Reactive Forms).

In addition to above, I'm getting "ERROR TypeError: control.registerOnChange is not a function" error when the page is loaded. I found following similar post on stackoverflow but I couldn't find solid answer for the issue I'm facing.

ERROR TypeError: control.registerOnChange is not a function

ERROR TypeError: control.registerOnChange is not a function --> formControlName

My component class looks like this

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  public myForm: FormGroup;
  public allCustomers: Customer[] = new Array();

  constructor(private formBuilder: FormBuilder) {}

  ngOnInit(): void {
    this.myForm = this.formBuilder.group({
      selectedCustomer: this.formBuilder.group({
        id: [],
        name:['']
      })
    })

    this.allCustomers.push(new Customer(0, "John"));
    this.allCustomers.push(new Customer(1, "Kumar"));
    this.allCustomers.push(new Customer(2, "Warma"));
    this.allCustomers.push(new Customer(3, "Sabitha"));
  }

  changeCustomer(e) {
    console.log(JSON.stringify(this.myForm.get('selectedCustomer').value));
  }
}

export class Customer {
  public id: number;
  public name: string;

  constructor(cusId: number, cusName: string) {
    this.id = cusId;
    this.name = cusName;
  }
}

My html page looks like this

<form name="frmMain" [formGroup]="myForm">
  <div>
    <div>
      All customers:
      <select (change)="changeCustomer($event)" formControlName="selectedCustomer">
        <option value="" disabled>Please select</option>
        <option *ngFor="let cus of allCustomers" [ngValue]="cus">{{cus.name}}</option>
      </select>
    </div>
    <br/>
    <div>
      Selected customer id :
      <span id="spnCustomerId">{{myForm.get('selectedCustomer').value.id}}</span>
    </div>
    <div>
      Selected customer name :
      <!-- I need to show selected customer name in below text box -->
      <input id="txtCustomerName" type="text"/>
    </div>
  </div>
</form>

Please see above example in stackblitz

1
  • Please, take a look to my answer, the problem is not the related by others Commented Jun 18, 2019 at 7:23

3 Answers 3

1

Sorry, the answers are incorrect. See the forked stackblitz

You are saying to Angular that selectedCustomer is a FormGroup

selectedCustomer: this.formBuilder.group({
        id: [],
        name:['']
      })

But you're trying to give as value to a FormGroup an object when you use select

<select (change)="changeCustomer($event)" formControlName="selectedCustomer">
        <option value="" disabled>Please select</option>
        <option *ngFor="let cus of allCustomers" 
             [ngValue]="cus">{{cus.name}}</option>
</select>

This is beacuse you has the error.

On solution is that selectedCustomer be an object, not a FormGroup, yes, a FormControl can store an object, not only a string or a number

this.myForm = this.formBuilder.group({
      selectedCustomer: []
    }) 

Of course, be carefully when you show the "name" and "id" using safe operator becaouse can be null

<span id="spnCustomerId">{{myForm.get('selectedCustomer').value?.id}}</span>
Sign up to request clarification or add additional context in comments.

Comments

1

The error happens, because you are initializing the form with the FormBuilder, but not all controls are present in the template (see here link).

Try this:

this.myForm = this.formBuilder.group({
  selectedCustomer: [''],
  name: ['']
})

Instead of adding a change listener, you can subcribe directly to the formControl as follows:

this.myForm.get('selectedCustomer').valueChanges
  .subscribe(e => {
    this.myForm.get('name').setValue(e.name);
    })

In the templatet:

<input id="txtCustomerName" type="text" formControlName="name"/>

3 Comments

Sorry, @riondo, I can not accept your answer as ok, the answer is other
@riorudo, first of all thank you for your solution and really appreciate your help. Without adding separate form control called "name: ['']", isn't there a way to get the customer name using "selectedCustomer" formControl?
You could do it like in the example from Eliseo and bind the value over the ngModel: <input id="txtCustomerName" type="text" [ngModel]="myForm.get('selectedCustomer').value?.name" [ngModelOptions]="{standalone: true}"/> Then you can remove "name" as formControl from myForm.
1

Try like this:

TS:

this.myForm = this.formBuilder.group({
  selectedCustomer: [],
  selectedCustomerName : []
})


changeCustomer(e) {
    console.log(JSON.stringify(this.myForm.get('selectedCustomer').value));
    let name = (this.myForm.get('selectedCustomer').value).name

    this.myForm.patchValue({
      selectedCustomerName : name
    });
  }

Template:

<div>
  Selected customer id :
  <span id="spnCustomerId">{{myForm.get('selectedCustomer').value?.id}}</span>
</div>
<input id="txtCustomerName" type="text" formControlName="selectedCustomerName"/>

3 Comments

You needn't add a new propertie to your formGroup, and not, it's not the problem
@Adrita Sharma, thank you for your answer. But your solution still gives me the mentioned error ("control.registerOnChange is not a function"). Also, without adding separate form control called "selectedCustomerName : ['']", isn't there a way to get the customer name using "selectedCustomer" formControl?
@Prabodha I have edited the answer, you won't be getting this error anymore. Also don't forget to add ? in {{myForm.get('selectedCustomer').value?.id}}

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.