Manzer A
Manzer A

Reputation: 3826

Using *ngFor with async pipe with conditional display in html in angular8

.html

<ng-container *ngFor="let contact of listContact | async; let index = index;">
      <h6 class="title" *ngIf="contact && contact['type']">
        {{contact['type']}}
        </h6>
   <div> {{contact['id']}}</div>
 </ng-container>

listContact an observable contains:-

[
  {
    "id": "u-8cf4161b-240f-5d7a-b5df-0522739c62d9",
    "type": "Peoples"
  },
  {
    "id": "u-0580ff64-c959-5690-bc54-16c43b28065d",
    "type": "Peoples"
  },
  {
    "id": "u-44e5a40a-a367-55e0-baf1-1eacccafe5f2",
    "type": "Teams"
  }
]

The expected(desired) html output:-

Peoples

u-8cf4161b-240f-5d7a-b5df-0522739c62d9
u-0580ff64-c959-5690-bc54-16c43b28065d

Teams
u-44e5a40a-a367-55e0-baf1-1eacccafe5f2

How to add a check that if previous {{contact['type']}} in for loop is same as current {{contact['type']}} in for loop , then not add {{contact['type']}} in view. title is dependent on {{contact['type']}} and too should not repeat until previous {{contact['type']}} is different from current one.

How to handle it in html for this issue?

Upvotes: 1

Views: 645

Answers (2)

Hien Nguyen
Hien Nguyen

Reputation: 18965

You can create a groupBy pipe

@Pipe({ name: "groupBy" })
export class GroupByPipe implements PipeTransform {
  transform(value: Array<any>, field: string): Array<any> {
    const groupedObj = value.reduce((prev, cur) => {
      if (!prev[cur[field]]) {
        prev[cur[field]] = [cur];
      } else {
        prev[cur[field]].push(cur);
      }
      return prev;
    }, {});
    return Object.keys(groupedObj).map(key => ({
      key,
      value: groupedObj[key]
    }));
  }
}

And use in html as

<ng-container *ngFor="let contact of listContact | groupBy:'type'; let index = index;">
      <h6 class="title">
        {{contact.key}}
        </h6>
   <div *ngFor="let value of contact.value">{{value.id}}</div>
 </ng-container>

Stackbliz https://stackblitz.com/edit/angular-groupby-pipe?

Upvotes: 1

yurzui
yurzui

Reputation: 214095

The right way to handle it would be grouping your items into categories like Peoples, Teams, etc.

But if you want to check your condition in template then you can store the result of listContact | async extract into a variable and then use index on it:

<ng-container *ngFor="let contact of listContact | async as contacts; let index = index;">
  <h6 class="title" *ngIf="contact.type && (!contacts[index - 1] || contacts[index - 1].type !== contacts[index].type)">
     {{contact.type}}
  </h6>
  <div> {{contact.id}}</div>
</ng-container>

Ng-run Example

Upvotes: 2

Related Questions