Home > other >  How do I loop over a slice of an array using ngFor?
How do I loop over a slice of an array using ngFor?

Time:12-18

I am creating a FAQ page with accordion buttons, with groups of buttons under sub-headers. I designed it using an ngFor statement in the faq.html file.

<h1>Frequently Asked Questions</h1>
<div *ngFor="let item of data; let i = index;">
    <button  (click)="toggleAccordion($event, i)"> {{item.parentName}} </button>
    <div  *ngFor="let child of item.childProperties" hide="!item.isActive">
    <p> {{child.propertyName}} </p>
</div>

Here is a snippet of the faq.ts file.

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

@Component({
  selector: 'app-faq',
  templateUrl: './faq.html',
  styleUrls: ['./faq.scss']
})
export class FaqComponent implements OnInit {
  data: any = [
    {
      parentName: 'Question 1A',
      childProperties: [{ propertyName: 'Answer 1A' }],
    },
    {
      parentName: 'Question 2A',
      childProperties: [{ propertyName: 'Answer 2A' }],
    },
    {
      parentName: 'Question 3A',
      childProperties: [{ propertyName: 'Answer 3A' }],
    },
    {
      parentName: 'Question 1B',
      childProperties: [{ propertyName: 'Answer 1B' }],
    },
    {
      parentName: 'Question 2B',
      childProperties: [{ propertyName: 'Answer 2B' }],
    },
  ];
}

I want to put sub-headers over Section A (Questions 1A, 2A, and 3A), and Section B (Questions 1B and 2B). I think I can use slice in the ngFor statement in faq.html, but the code won't compile.

I tried this slice pipe:

<div *ngFor="let item of data | slice:0:2; let i = index;">

What should I change to get it to compile and break up the FAQ sections? Is the slice pipe the way to go?

CodePudding user response:

The problem here is that the slice pipe returns your data as type unknown.

There are a couple of ways around this:

$any

<p *ngFor="let item of data | slice:2:4">
  {{ $any(item).parentName }}
</p>

Bracket notation

<p *ngFor="let item of data | slice:2:4">
  {{ item['parentName'] }}
</p>

A function

slicedData(data : any[]) : any[] {
  return data.slice(2,4)
}
<p *ngFor="let item of slicedData(data)">
  {{ item['parentName'] }}
</p>

You might want to properly type your data though, instead of using any. It is called Typescript for a reason after all.

Here are some examples in a Stackblitz.

CodePudding user response:

I had to change the html to access the properties in different way and it got compiled:

<div *ngFor="let item of data; let i = index;">
    <button  (click)="toggleAccordion($event, i)"> {{item['parentName']}} </button>
    <div  *ngFor="let child of item['childProperties'] | slice:0:2; let i = index;" hide="!item.isActive">
    <p> {{child['propertyName']}} </p>
</div>

CodePudding user response:

You can just add one *ngIf and check if i < 3:

<h1>Frequently Asked Questions</h1>
<div *ngFor="let item of data; let i = index;">
  <ng-container *ngIf="i < 3">
    <button  (click)="toggleAccordion($event, i)"> {{item.parentName}} </button>
    <div  *ngFor="let child of item.childProperties" hide="!item.isActive">
    <p> {{child.propertyName}} </p>
  </ng-container>
</div>

CodePudding user response:

Thank you for your help, everyone. I changed faq.html to:

<h1>Frequently Asked Questions</h1>
<h2>General</h2>
<div *ngFor="let item of data; let i = index;">
  <ng-container *ngIf="i < 3">
    <button  (click)="toggleAccordion($event, i)"> {{item.parentName}} </button>
    <div  hide="!item.isActive">
    <p> {{item.childName}} </p>
</div>

and it worked.

  • Related