2

In db table, I have "key_name" which is successfully returning in API and working great.

What I want to do is to set those fields value as a formControlName in html and in component I am using the reactive form so I have tried formArrayName.

Based on the change event I am pushing new formControl in categoryArray and assigning its key as db field's value.

here is my Html:

<div class="col-md-6">
                            <div formArrayName="categoryArray" *ngFor="let type of types; let k = index">
                                <div [formGroupName]="k">
                                    <div class="form-group">
                                        <label>Select {{ type.cat_name }}</label>
                                        <select class="form-control custom-select" 
                                            (change)="onChangeType($event.target.value)"
                                            formControlName="{{ type.key_name }}" >
                                            <option value="">-- Select --</option>
                                            <option *ngFor="let type of types" [value]="type.category_id">
                                                {{type.cat_name}}
                                            </option>
                                        </select>
                                    </div>
                                </div>
                            </div>
                        </div>

component.ts:

onChangeCategory(id) {
    if(id) {
      this.artistService.fetchTypeAndSubTypes(id).subscribe(res => {
        if (res.status == 200) {
          this.types = res.data

          this.addInNewCategory(this.types)

        }
      })
    } else {
      this.types = null
      this.subTypes = null
    }
  }

  get category(): FormArray {
    return <FormArray>this.uploadArtWorkForm.controls.categoryArray;
  }

  addInNewCategory(types) {
    let obj = {}

    types.forEach(element => {
      obj[element['key_name']] = [null, [Validators.required]]
    });

    console.log("obj", obj)
    this.category.push(
      this.formBuilder.group(obj)   
    );

  }

What I want to archive is that based on 1st category selection all 2nd level category will be shown as a dynamic HTML dropdown who has their child category listing in the dropdown.

Errors that I am getting:

ERROR Error: Cannot find control with path: 'categoryArray -> 1'

ERROR Error: Cannot find control with path: 'categoryArray -> 1 -> metal'

EDIT: After setting up form control name, How can I set each newly created dropdown's value ? I need to fetch it from the db.

Here is Stackblitz: https://stackblitz.com/edit/dyncamic-populating-dropdown

Thanks in advance

10
  • can you create a stackblitz instance of your issue? Commented Apr 20, 2020 at 6:35
  • @Prince Not possible Commented Apr 20, 2020 at 6:55
  • I don't really understand the problem. Why is not possible to create a stackblitz if you want people to help you? Commented Apr 21, 2020 at 0:45
  • @trungk18 added stackblitz Commented Apr 21, 2020 at 5:03
  • @Prince added stackblitz Commented Apr 21, 2020 at 5:04

2 Answers 2

4

Tried modifying your code myself at least the errors below are fixed:

ERROR Error: Cannot find control with path: 'categoryArray -> 1'

ERROR Error: Cannot find control with path: 'categoryArray -> 1 -> metal'

But you still need to improve on your end using my solution.

Modify your app.component.html as below:

<form [formGroup]="uploadArtWorkForm" (ngSubmit)="addUploadArtWorkForm();">
    <div class="col-md-6">
        <div class="form-group">
            <label>Select Category:</label>
      <select class="form-control custom-select" formControlName="cat_id" [ngClass]="{'is-invalid': uploadArtWorkForm.controls['cat_id'].invalid && (uploadArtWorkForm.controls['cat_id'].dirty || uploadArtWorkForm.controls['cat_id'].touched || isFormSubmitted) }" (change)="onChangeCategory($event, $event.target.value)">
        <option value="">-- Select --</option>
        <option *ngFor="let category of parentCategories" [value] ="category.category_id">
            {{category.cat_name}}
        </option>
      </select>
            <div class="invalid-feedback" *ngIf="uploadArtWorkForm.controls['cat_id'].errors">
                <div *ngIf="uploadArtWorkForm.controls['cat_id'].errors.required">Category is
                    required.</div>
            </div>
        </div>
    </div>
    <div class="col-md-6" formArrayName="categoryArray" *ngIf="uploadArtWorkForm.get('categoryArray')['controls'].length > 0">
        <div  *ngFor="let item of uploadArtWorkForm.get('categoryArray')['controls']; let k = index">
            <div [formGroup]="item">
                <div class="form-group ">
                    <label>Select {{ types[k].cat_name }}</label>
                    <select class="form-control custom-select" [class]="types[k].key_name" (change)="onChangeType($event.target.value)" formControlName="{{ types[k].key_name }}" *ngIf="types[k].cat_name == 'Type'"> 
              <option value="">-- Select --</option>
              <option *ngFor="let type of catTypeValue" [value]="type.category_id">
                  {{type.cat_name}}
              </option>
          </select>
          <select class="form-control custom-select" [class]="types[k].key_name" (change)="onChangeType($event.target.value)" formControlName="{{ types[k].key_name }}" *ngIf="types[k].cat_name == 'Metal'">
              <option value="">-- Select --</option>
              <option *ngFor="let type of catMetalValue" [value]="type.category_id">
                  {{type.cat_name}}
              </option>
          </select>
          <select class="form-control custom-select" [class]="types[k].key_name" (change)="onChangeType($event.target.value)" formControlName="{{ types[k].key_name }}" *ngIf="types[k].cat_name == 'Gems'">
              <option value="">-- Select --</option>
              <option *ngFor="let type of catGemsValue" [value]="type.category_id">
                  {{type.cat_name}}
              </option>
          </select>
                </div>
            </div>
        </div>
    </div>
</form>

and app.component.ts as below:

import { Component } from "@angular/core";
import { FormGroup, FormBuilder, Validators, FormArray, FormControl } from "@angular/forms";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  uploadArtWorkForm: any;
  uploadArtWorkForm1: any;
  isFormSubmitted: boolean = false;

  parentCategories = [
    {"parent_id":0,"cat_name":"Jewelry","category_id":1},
    {"parent_id":0,"cat_name":"Painting","category_id":16},
    {"parent_id":0,"cat_name":"Photograph","category_id":22}];
  types;
  subTypes;

  //below value will be displayed in Select Type dropdown
  catTypeValue = [
    {"parent_id":2,"cat_name":"Anklets","category_id":3,"key_name":"anklets"},
    {"parent_id":2,
    "cat_name":"Body",
    "category_id":4,
    "key_name":"body"},
    {"parent_id":2,"cat_name":"Bracelets","category_id":5,
    "key_name":""},
    {"parent_id":2,
    "cat_name":"Charms","category_id":6,
    "key_name":""},
    {"parent_id":2,"cat_name":"Necklaces","category_id":7,
    "key_name":""},
    {"parent_id":2,"cat_name":"Ornamental","category_id":8,
    "key_name":""},
    {"parent_id":2,
    "cat_name":"Rings & Studs","category_id":9,
    "key_name":""},
    {"parent_id":2,
    "cat_name":"Jewelry Metal","category_id":10,"key_name":""},{"parent_id":2,
    "cat_name":"Yellow Gold","category_id":11,
    "key_name":""},
    {"parent_id":2,
    "cat_name":"White Gold","category_id":12,"key_name":"whitegold"},{"parent_id":2,
    "cat_name":"Silver","category_id":13,"key_name":"silver"}
    ]

  // below values will be displayed in Select Metal dd
  catMetalValue = [
    {"parent_id":14,"cat_name":"White Gold","category_id":24,"key_name":"whitegold"},
    {"parent_id":14,"cat_name":"Yellow Gold","category_id":24,"key_name":"whitegold"},
    ]

  // below values will be displayed in Select Gems dd
  catGemsValue = [
    {"parent_id":15,"cat_name":"Blue Gems","category_id":25,"key_name":"bluegems"}
    ]

  constructor(private formBuilder: FormBuilder) {
    this.uploadArtWorkForm = this.formBuilder.group({
    cat_id: new FormControl('', Validators.required),
    categoryArray: this.formBuilder.array([]),
  });
  }
  ngOnInit() {}
  onChangeType(value, id){
    console.log(value)
// solution to https://stackoverflow.com/questions/61315779/angular-8-not-getting-selected-dropdown-values-in-component-using-reactive-form?noredirect=1&lq=1
  }
  onChangeCategory(event, id) {
    if (id) {
      this.types = [
        {"parent_id":1,
        "cat_name":"Type",
        "category_id":2,
        "key_name":"type"},
        {"parent_id":1,
        "cat_name":"Metal",
        "category_id":14,
        "key_name":"metal"},
        {"parent_id":1,
        "cat_name":"Gems",
        "category_id":15,
        "key_name":"gems"}];
      if(this.uploadArtWorkForm.controls['categoryArray'].length > 0){
        this.uploadArtWorkForm.controls['categoryArray'].controls.length = 0
      }
      this.addInNewCategory(this.types);
    } else {
      this.types = null;
      this.subTypes = null;
    }
  }

  get category(): FormArray {
    return <FormArray>this.uploadArtWorkForm.controls['categoryArray'];
  }

  addInNewCategory(types) {['categoryArray'];
    types.forEach((element, i) => {
      this.category.push(this.formBuilder.group({[element["key_name"]]: new FormControl(element["key_name"])
      }));
    });
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

this will also fix for solution you have asked in stackoverflow.com/questions/61315779/…
-1

Try Below,

Suppose you are getting from keys in formKeys Object

let formObj={};
Object.keys(this.formKeys||[]).forEach(d=>{
 formObj[k]=["",Validators.required];
});

this.dynamicForm=this.fb.group(formObj);

In html:

<form [formGroup]="dynamicForm">
<div *ngFor="let key of ArrayOfFormKey">
  <input [fromControlName]="key">
</div>
</form>

1 Comment

What you are suggesting is good, How can I fetch each newly created dropdown's value and show it in their respective dropdown ?

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.