Triggher method call on updating a field value

59 Views Asked by At

I'm having fun with Angular Forms and primeNG. I have a form with 2 p-dropdown: when i select a value from the first dropdown (the report Type) I have to update the values of the second one since they depend from the choice of the first one (display the values connected to the report Type).

In particular I need to trigger the getFilteredReports() method when the value of selectedReportType is updated (from the first dropdown indeed).

In the first dropdown I've used the ngOnChanges since I had the same problem and the initial reports are coming from an @Input().

Here's the relevant code for the second case:

selectedReportType: ReportType = { label: '' };

  getFilteredReports() {
    return this.currentReportSubset = this.reportTypeAndSubset.get(this.selectedReportType?.label) ?? [];
  }

At the moment in my template I have the second dropdown with this line that retrieves the values

<p-dropdown
....
    [options]="getFilteredReports()"
....
</p-dropdown>

I absolutely want to avoid methods calls in the template since it's a bad practice and I'm using the CD On Push if this can be of any help.

If, of any help, that's the code of the first dropdown:

 <p-dropdown
      [options]="reportTypes"
      optionLabel="label"
      [filter]="true"
      filterBy="label"
      [(ngModel)]="selectedReportType"
      name="pickedReportType"
    >
      <ng-template let-selectedReport pTemplate="selectedItem">
        <div *ngIf="selectedReport">
          <div>{{ selectedReport.label }}</div>
        </div>
      </ng-template>
      <ng-template let-report pTemplate="item">
        <div>
          <div>{{ report.label }}</div>
        </div>
      </ng-template>
    </p-dropdown>

What is a clean way to do it?

1

There are 1 best solutions below

4
Shai On

You can call the getFilteredReports method when the first dropdown's value changes and then provide currentReportSubset to the second dropdown, like this:

In your ts file:

selectedReportType: ReportType = { label: '' };

getFilteredReports() {
    this.filteredReports = this.reportTypeAndSubset.get(this.selectedReportType?.label) ?? [];
}

In your html file:

<!-- First dropdown -->
<p-dropdown
    [options]="reportTypes"
    optionLabel="label"
    [filter]="true"
    filterBy="label"
    [(ngModel)]="selectedReportType"
    name="pickedReportType"
    (onChange)="getFilteredReports()"
>
  <ng-template let-selectedReport pTemplate="selectedItem">
    <div *ngIf="selectedReport">
      <div>{{ selectedReport.label }}</div>
    </div>
  </ng-template>
  <ng-template let-report pTemplate="item">
    <div>
      <div>{{ report.label }}</div>
    </div>
  </ng-template>
</p-dropdown>


<!-- Second dropdown -->
<p-dropdown
....
    [options]="filteredReports"
....
</p-dropdown>

In case it doesn't work right away, you're probably calling the getFilteredReports method asynchronously so you'll also need to let the change detector know it needs to do its thing:

getFilteredReports() {
    this.filteredReports = this.reportTypeAndSubset.get(this.selectedReportType?.label) ?? [];
    this.changeDetector.markForCheck();
}