How do I loop over a slice of an array using ngFor?
Asked Answered
L

5

5

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 class="accordion" (click)="toggleAccordion($event, i)"> {{item.parentName}} </button>
    <div class="panel" *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?

Lair answered 16/12, 2021 at 23:16 Comment(0)
L
4

Slicing Your Data

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.

Larrigan answered 17/12, 2021 at 0:42 Comment(1)
Thank you. I will try this out.Lair
A
2

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 class="accordion" (click)="toggleAccordion($event, i)"> {{item['parentName']}} </button>
    <div class="panel" *ngFor="let child of item['childProperties'] | slice:0:2; let i = index;" hide="!item.isActive">
    <p> {{child['propertyName']}} </p>
</div>
Amoeba answered 17/12, 2021 at 0:18 Comment(0)
H
1

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 class="accordion" (click)="toggleAccordion($event, i)"> {{item.parentName}} </button>
    <div class="panel" *ngFor="let child of item.childProperties" hide="!item.isActive">
    <p> {{child.propertyName}} </p>
  </ng-container>
</div>
Hg answered 17/12, 2021 at 0:56 Comment(0)
L
1

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 class="accordion" (click)="toggleAccordion($event, i)"> {{item.parentName}} </button>
    <div class="panel" hide="!item.isActive">
    <p> {{item.childName}} </p>
</div>

and it worked.

Lair answered 17/12, 2021 at 18:53 Comment(0)
C
0

In your .ts component, declare your variable as below

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' }],
    },
];
Conservator answered 11/8, 2023 at 22:19 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Patiencepatient

© 2022 - 2024 — McMap. All rights reserved.