Search code examples
angularngforviewchild

Select a particular child component looped inside a ngFor in the parent


I have a list of mat-expansion-panels in below HTML. A user can add any number of panels by clicking the add button.

Parent Component HTML

    <mat-accordion>
        <ng-container *ngFor="let item of items; let i = index;">
            <mat-expansion-panel (opened)="setOpened(i)" (closed)="setClosed(i)" hideToggle="true">
                <mat-expansion-panel-header [collapsedHeight]="'66px'" [expandedHeight]="'60px'">
                    <div class = "nc-rsc-wrapper">
                        <app-resource-summary-card [resourceData] = "item.resCategory"></app-resource-summary-card>
                    </div>
                </mat-expansion-panel-header>
                <div class = "">
                    <app-resource-edit (resourceDataEmitter)="collectResourceData($event, i)" id = "matExp"></app-resource-edit>
                </div>
             </mat-expansion-panel>
         </ng-container>
     </mat-accordion>
     <button mat-button (click)="addResource()" class = "mt-3">ADD RESOURCE</button>

Users can expand the mat-expansion-panels and edit the form given inside the app-resource-edit component. However, I want to get the form status of a particular expansion panel when the user closes it. I managed to get the form status using viewChild, but it returns only the status of the first expansion panel's form.

Parent.component.ts:

@ViewChild(ResourceEditComponent) resEditCmp: ResourceEditComponent;

setClosed(itemIndex) {
    if (this.resEditCmp.resourceEditForm.invalid){
      this.items[itemIndex].valid = false;
      console.log(this.items[itemIndex].valid);
    }
    else if (this.resEditCmp.resourceEditForm.valid){
      this.items[itemIndex].valid = true;
      console.log(this.items[itemIndex].valid);
    }
  }

Does anyone know how to select a particular child component looped inside a ngFor in the parent?

EDIT:

Child Component

<form [formGroup]="resourceEditForm">
    <div class="row">
        <div class="col-4">
            <mat-form-field class="col-12 example-full-width" appearance="outline">
                <mat-label>Resource Category</mat-label>
                <mat-select formControlName="resCategory" (selectionChange)="loadForm($event)">
                    <mat-option value="airtime">Airtime</mat-option>
                    <mat-option value="sms">SMS</mat-option>
                    <mat-option value="voice">Voice</mat-option>
                    <mat-option value="data">Datapack</mat-option>
                </mat-select>
            </mat-form-field>
        </div>
        <div class="col-4">
            <mat-form-field class="col-12 example-full-width" appearance="outline">
                <mat-label>Quantity</mat-label>
                <input matInput placeholder="" formControlName="quantity" value="">
            </mat-form-field>
        </div>
        <div class="col-4">
            <mat-form-field class="col-12 example-full-width" appearance="outline">
                <mat-label>Validity Period</mat-label>
                <input matInput placeholder="" formControlName="validityPeriod" value="">
            </mat-form-field>
        </div>
        <div class="col-4" *ngIf="selectedFormName==='sms' || selectedFormName==='voice' || selectedFormName==='data'">
            <mat-form-field class="col-12 example-full-width" appearance="outline">
                <mat-label>Type</mat-label>
                <input matInput placeholder="" formControlName="type" value="">
            </mat-form-field>
        </div>
        <div class="col-4" *ngIf="selectedFormName==='data'">
            <mat-form-field class="col-12 example-full-width" appearance="outline">
                <mat-label>Pack Type</mat-label>
                <input matInput placeholder="" formControlName="packType" value="">
            </mat-form-field>
        </div>
    </div>
    <button mat-button (click)="save()">Next</button>
</form>

ngOnInit(){
    this.resourceEditForm = this.formBuilder.group({
      resCategory: ['', Validators.required],
      quantity: ['', Validators.required],
      validityPeriod: ['', Validators.required],
      type: ['', Validators.required],
      packType: ['', Validators.required]
    });
  }

Solution

  • Get all ResourceEditComponent as query list;

    @ViewChildren(ResourceEditComponent) resEditCmp:  QueryList<ElementRef>;
    

    Then take the selected item in the list by index

    setClosed(itemIndex) {
    let currentresEditCmp = this.resEditCmp[itemIndex];
       
      }