Search code examples
angularangular-materialangular12

Using Object Parameter to pull another Object


Re-introducing myself to Angular, wanted to ask a question. I am pulling appointment data into my fields, and I need to pull the user name up using the "UserId" parameter in the appointment object, and having that pull up the user using the "UserId" parameter in users, and THEN display the name. They're all coming into my console just fine, but how exactly do I write it in the frontend to do this?

        <mat-accordion>
        <mat-expansion-panel class="content" *ngFor="let app of appointments, let i = index">
          <mat-expansion-panel-header *ngFor="let user of users">
            <mat-panel-title>Image: </mat-panel-title>
            <mat-panel-title ***ngIf="app.UserId === user?.UserId">Client: {{user?.ContactId}}**</mat-panel-title>
            <mat-panel-title>Location: {{this.currentLocation}}</mat-panel-title>
            <mat-panel-title>Date: {{app.StartDate| date : 'MM-dd-yyyy'}}</mat-panel-title>
            <mat-panel-title>Time: {{app.StartDate| date : 'hh:mm'}}</mat-panel-title>
            <i class="material-icons-outlined" style="align-self: end">expand_more</i>
          </mat-expansion-panel-header>
          <mat-panel-description>
            <p>Desc: {{app.Description}}</p>
          </mat-panel-description>
        </mat-expansion-panel>
    </mat-accordion>

Solution

  • What your after is a pipe to filter through your data. Lets go through a simple example.

    A pipe would look something like this filter-user.pipe.ts:

    import { Pipe, PipeTransform } from '@angular/core';
    
    @Pipe({
      name: 'filterUser',
      pure: false
    })
    export class FilterUserPipe implements PipeTransform {
      transform(users: string[], filterUser: string): any {
        if (!users || !filterUser) {
          return users;
        }
    
        return users.filter(user => user === filterUser);
      }
    }
    
    

    Your component with your data of appointments and users app.component.ts:

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'my-app',
      styleUrls: ['./app.component.scss'],
      templateUrl: './app.component.html'
    })
    export class AppComponent {
    
      // your Appointments
      appointments: Appointment[] = [
        {
          name: 'Brolly',
          surname: 'Patel',
          date: new Date()
        },
        {
          name: 'Goku',
          surname: 'Smith',
          date: new Date()
        },
        {
          name: 'jimmy',
          surname: 'Smith',
          date: new Date()
        }
      ];
    
      // your Users
      users: string[] = ['John', 'Brolly', 'Goku', 'Gohan'];
    }
    
    // Interface you may want to put in another separate file.
    export interface Appointment {
      name: string;
      surname: string;
      date: Date;
    }
    

    Keeping it simple to help you understand, I've rendered the following HTML app.component.html:

    <div *ngFor="let appointment of appointments">
      <div *ngFor="let user of users | filterUser: appointment.name">
        {{user}}
      </div>
    </div>
    

    When you create your pipe remember to add it into your concerning module in the declarations array. (I say concerning module as it helps with lazy loading) app.module.ts:

    import { AppComponent } from './app.component';
    import { CoreModule } from './core';
    import { FilterUserPipe } from './filter-user.pipe';
    import { HelloFrameworkModule } from './hello-framework';
    import { BrowserModule } from '@angular/platform-browser';
    
    @NgModule({
      bootstrap: [AppComponent],
      declarations: [AppComponent, FilterUserPipe],
      imports: [BrowserModule, CoreModule, HelloFrameworkModule]
    })
    export class AppModule {}
    
    

    Your output would be the following:

    Brolly
    Goku
    

    So in your code example this is how it would look:

    // Your HTML would roughly look like this:
    <mat-accordion>
      <mat-expansion-panel class="content" *ngFor="let app of appointments, let i = index">
        <mat-expansion-panel-header *ngFor="let user of users | filterUser: app.UserId">
          <mat-panel-title>Image: </mat-panel-title>
          <mat-panel-title>Client: {{user?.ContactId}}**</mat-panel-title>
          <mat-panel-title>Location: {{this.currentLocation}}</mat-panel-title>
          <mat-panel-title>Date: {{app.StartDate| date : 'MM-dd-yyyy'}}</mat-panel-title>
          <mat-panel-title>Time: {{app.StartDate| date : 'hh:mm'}}</mat-panel-title>
          <i class="material-icons-outlined" style="align-self: end">expand_more</i>
        </mat-expansion-panel-header>
        <mat-panel-description>
          <p>Desc: {{app.Description}}</p>
        </mat-panel-description>
      </mat-expansion-panel>
    </mat-accordion>
    
    // Your pipe would need modifying slightly as your using an object:
    export class FilterUserPipe implements PipeTransform {
      transform(users: string[], filterUserId: string): any {
        if (!users || !filterUserId) {
          return users;
        }
    
        return users.filter(user => user.UserId === filterUserId);
      }
    }