0

I trying to add a nested drop-down. If we click "Add City", it will create another drop-down. I was successful without drop-down. Please see bellow

enter image description here

..component.html

<form [formGroup]="form" (ngSubmit)="onSubmit()">
  <select  formControlName="cities">
    <option *ngFor="let city of myCities; let i=index" [value]='itemname' >
      {{ city }}
    </option>
  </select>
  <br>
  <button>Submit</button>
  <button (click)="addCity()">Add City</button>
  <button (click)="remove(i)">Remove</button>
</form>

component.ts

 form = new FormGroup({
    cities: new FormControl([null]),
  });


  myCities = ['Dhaka','Dubai','Munich'];


  get cities(): FormArray { return this.form.get('cities') as FormArray; }

  addCity() { this.form.get('cities').push(new FormControl())}

  remove(index){ this.form.get('cities').removeAt(index) }

Showing error as bellow:

E:/angular/nestedForm2/src/app/order-form/order-form.component.ts (21,39): Property 'push' does not exist on type 'AbstractControl'.

E:/angular/nestedForm2/src/app/order-form/order-form.component.ts (23,42): Property 'removeAt' does not exist on type 'AbstractControl'.

I have tried in different ways but still did not find any solution. Could you please help?

2 Answers 2

1

To get around the errors you have, you need to cast your AbstractControl to its subclass FormArray where push and removeAt are defined.

(this.form.get('cities') as FormArray).push(new FormControl())
(this.form.get('cities') as FormArray).removeAt(index)

You have to do this because TypeScript cannot determine the exact type of form.get('cities'), since you're accessing it by providing a string. Only you as a developer know, based on the structure of the data in your form, that form.get('cities') will contain a FormArray.

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

6 Comments

Thank you Lazar. Could you please tell me how can I cast?
I've provided a code snippet in my answer. You use as to cast, as I've shown there.
I have done this addCity() { (this.form.get('cities') as FormArray).push(new FormControl())} & remove(index){ (this.form.get('cities') as FormArray).removeAt(index) }. But still find error "ERROR TypeError: this.form.get(...).push is not a function"
That's a runtime error and has nothing to do with your question. It means that your logic is bad.
Is there any way out to make nested drop-down ?
|
0

I found the solution.

component.html:

<form [formGroup]="form" (ngSubmit)="onSubmit()">
    <div formArrayName="cities">

      <div *ngFor="let city of cities.controls; let i=index">

        <select [formControlName]="i">

            <option *ngFor="let itemname of myCities" [value]='itemname' >
                {{ itemname }}
            </option>

        </select> 

      </div>

    </div>

    <br>

    <button>Submit</button>
  </form>

  <br>

  <button (click)="addCity()">Add City</button>
  <button (click)="remove(i)">Remove City</button>

component.ts:

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

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

  form = new FormGroup({
    cities: new FormArray([
      new FormControl([null]),
    ]),
  });



  myCities = ['Dhaka','Dubai','Munich'];


  get cities(): FormArray { return this.form.get('cities') as FormArray; }

    addCity() { this.cities.push(new FormControl()); }

    remove(index) { (this.form.get('cities') as FormArray).removeAt(index) }

  constructor() { }

  ngOnInit() {
  }

  onSubmit() {
    console.log(this.cities.value);  // ['SF', 'NY']
    console.log(this.form.value);    // { cities: ['SF', 'NY'] }
  }

  setPreset() { this.cities.patchValue(['LA', 'MTV']); }


}

Comments

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.