Home > Software engineering >  Angular 15, child component doesn't emit string to parent
Angular 15, child component doesn't emit string to parent

Time:01-19

I have this child component (filters.component.ts) from which I am trying to emit a string to the parent component. I had already done this once with a different component but it seems like Angular doesn't like me implementing an *ngFor to loop through a string array and pass the category string to the method? I've tried adding a console log to the onShowCategory() method in home.component.ts and it does not log any string values to the console, leading me to believe that the values are not being passed to the parent when the click event is activated. Here is the code (I've added arrows to point to the relevant lines of code, they are not part of my code and not the issue.):

filters.component.html:

<mat-expansion-panel *ngIf="categories">
    <mat-expansion-panel-header>
        <mat-panel-title>CATEGORIES</mat-panel-title>
    </mat-expansion-panel-header>
    <mat-selection-list [multiple]="false">
        <mat-list-option *ngFor="let category of categories" [value]="category"> <--------
            <button (click)="onShowCategory(category)">{{ category }}</button> <--------
        </mat-list-option>
    </mat-selection-list>
</mat-expansion-panel>

filters.component.ts:

@Component({
  selector: 'app-filters',
  templateUrl: './filters.component.html',
  styleUrls: []
})
export class FiltersComponent {
  @Output() showCategory = new EventEmitter<string>() <-------

  categories: string[] = ['shoes', 'sports']; <-------

  onShowCategory(category: string): void { <-------
    this.showCategory.emit(category); <-------
  }
}

home.component.html:

<mat-drawer-container [autosize]="true" >
    <mat-drawer mode="side"  opened>
        <app-filters (showCategory)="onShowCategory($event)"></app-filters> <-------
    </mat-drawer>
    
    <mat-drawer-content >
        <app-products-header (columnsCountChange)="onColumnsCountChange($event)"></app-products-header>
        
        {{ category }} <----- should display the category when selected
    </mat-drawer-content>
</mat-drawer-container>

home.component.ts:

import { Component } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: []
})
export class HomeComponent {
  cols = 3;
  category: string | undefined; <-------
  
  onColumnsCountChange(colsNumber: number): void {
    this.cols = colsNumber
  }
 
  onShowCategory(newCategory: string): void { <-------
    this.category = newCategory; <-------
  }
}

I have read through and followed the variables many times and I don't see the issue. From the child component template I pass the category to the onShowCategory method and emit it to the parent. From the parent I call the EventEmitter and pass the $event variable which should change the value of the category property in the home component. I've checked spelling, and tried moving the tags around. I don't see a console.log in the console when I add one to the method, and I cannot get the string to appear on the home template. What am I doing wrong?

CodePudding user response:

your parent html should have messageEvent. Give this a try and see if it works.

<app-filters (messageEvent)="onShowCategory($event)"></app-filters>

<app-products-header (messageEvent)="onColumnsCountChange($event)"></app-products-header>

I also like to put console.log statements at every point when setting up EventEmitters, just to see where it's getting stuck.

CodePudding user response:

After taking a break and spending a few more hours combing the internet for answers (to no avail) I decided to try something completely unintuitive and solved it.

I changed:

<mat-list-option *ngFor="let category of categories" [value]="category">
            <button type="button" (click)="onShowCategory(category)">{{ category }}</button>
        </mat-list-option>

To

<mat-list-option *ngFor="let category of categories" (click)="onShowCategory(category)" [value]="category">
      <div>{{ category }}</div>
</mat-list-option>

and now it works, not entirely sure why the click event needs to be on the parent tag and cannot be on the button itself. The thought process that got me to this solution was that the click event seemed to not be activating and/or the strings in the categories array weren't being passed to the method properly. I hope this helps someone in the future.

  • Related