Showing a header 2 element just once using both *ngFor and *ngIf in Angular

I have an array of words with varying lengths. I am using ng-For to loop through the array and ng-if to display the words based on their lengths, but I am struggling to add titles to separate them.

Expected Outcome:

2 letter words: to, am, as...

3 letter words: the, bee, sin...

And so on...

This is what I have so far:

<div *ngIf="data">
  <h2 class="title">{{data.letters}}</h2>
  <ul class="wordList" *ngFor="let item of data.word">
      <li *ngIf="item.length ==2">{{item}}</li>
      <li *ngIf="item.length ==3">{{item}}</li>
      <li *ngIf="item.length ==4">{{item}}</li>
      <li *ngIf="item.length ==5">{{item}}</li>
      <li *ngIf="item.length ==6">{{item}}</li>
      <li *ngIf="item.length ==7">{{item}}</li>
      <li *ngIf="item.length ==8">{{item}}</li>
      <li *ngIf="item.length ==9">{{item}}</li>
      <li *ngIf="item.length ==10">{{item}}</li>
      <li *ngIf="item.length ==11">{{item}}</li>
      <li *ngIf="item.length ==12">{{item}}</li>
      <li *ngIf="item.length ==13">{{item}}</li>
      <li *ngIf="item.length ==14">{{item}}</li>

    </ul>
</div>

I know I should also use an index to iterate through the word sizes, but I will address that later :)

Answer №1

Utilize a Pipe to convert an array of words into an object where the length of the word acts as the key and the words themselves are the values.

@Pipe({ name: 'groupByLengthPipe' })
export class GroupByLengthPipe implements PipeTransform {

    transform(input: []) {
        let map = {};
        input.forEach((e: string) => {
            if (map[e.length]) {
                map[e.length] = map[e.length] + ' ' + e;
            } else {
                map[e.length] = e;
            }
        });
        return map;
    }

}

You can now easily implement this in your template using the syntax below:

<div *ngFor="let word of words | groupByLengthPipe | keyvalue">
    <h2>{{word.key}}</h2> letter words : {{word.value}}
</div>

Answer №2

It seems like the best approach would be to handle the process of grouping by length within your class and create a structured object to store the data for display purposes. It's important to note that you have a list of groups based on word length, as well as a list of words for each specific group, which means you will need to utilize two nested *ngFor loops.

Within your class:

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
  private words = ['the', 'to', 'am', 'as', 'bee', 'sin', 'other'];
  groupedByLength: { length: string, words: string[] }[] = [];

  ngOnInit() {
    this.groupByLength();
  }

  private groupByLength() {
    let grouped = {};
    for(let word of this.words) {
      const length = word.length;
      if(!grouped[length]) {
        grouped[length] = [word];
      } else {
        grouped[length].push(word);
      }
    }
    Object.keys(grouped).forEach(key => {
      this.groupedByLength.push({ length: key, words: grouped[key] });
    });
  }
}

In your template:

<div *ngFor="let data of groupedByLength">
    <h2>{{ data.length }} letter words:</h2>
    <ul>
        <li *ngFor="let word of data.words">{{ word }}</li>
    </ul>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to connect to the directive even after adding it as an input

In the error message below, it seems that suggestion 1 might be applicable to my situation. My Angular component has a GcUser input, but I have confirmed that it is part of the module (both the component behind the HTML and the user-detail component import ...

Issue with <BrowserRouter>: TS2769: No suitable overload for this call available

I encountered this error and have been unable to find a solution online. As a beginner in typescript, I am struggling to resolve it. The project was originally in JavaScript and is now being migrated to TypeScript using ts-migrate. I am currently fixing er ...

When I attempt to conceal the filter within mat-table using *ngIf, I encounter an issue where I am unable to read the property 'value' due to it being

After creating a mat-table, I encountered an issue when trying to show and hide my input filter area using a button. If I use *ngIf="showInputFilter" to hide the filter area, I receive the error message Cannot read property 'value' of u ...

Utilizing Express JS to Optimize JPEG File Loading with Cache Headers

I have been working on implementing Cache-Control for my static image files. I have successfully set this header for HTML and JS files: https://i.stack.imgur.com/9VuWl.png However, I am facing challenges with JPEG files: https://i.stack.imgur.com/p52jm. ...

Creating nested directories in PHP using arrays: A step-by-step guide

When working with Laravel, I encountered an issue while trying to create a trait file using the console. The problem arises when specifying a directory for the file creation - it does not get created as expected. The structure of the directory can be dyna ...

The issue at hand is that web components within Angular are failing to register changes

I have created a custom element for a todo item using custom element js. I am using this custom element in an Angular file and able to pass properties. The issue I am facing is that whenever I add or delete a new item, it's not reflecting in the custo ...

Step-by-step guide for implementing Angular on a production server with the latest universal server rendering feature in angular-cli

I have successfully deployed my Angular application on Azure Server using angular-cli. By running the command ng build --prod --aot and transferring files from the /dist folder to the root website folder, everything is working perfectly! To address SEO c ...

How to dynamically update a list in a React autocomplete input field?

Currently, I am developing an address autocomplete feature that utilizes the Google Places autocomplete API. To fetch data while the user types, I have implemented React Query and utilized a <datalist> where I iterate over the array to display <o ...

Verification based on conditions for Angular reactive forms

I am currently learning Angular and working on creating a reactive form. Within my HTML table, I have generated controls by looping through the data. I am looking to add validation based on the following cases: Upon page load, the Save button should be ...

Typescript - using optional type predicates

I'm looking to create a custom type predicate function that can accurately determine if a number is real and tighten the type as well: function isRealNumber(input: number | undefined | null): input is number { return input !== undefined && ...

Troubleshooting issues with Docker and Angular 2: unable to retrieve data

We are in the process of setting up an Angular 2 application with Docker by following a tutorial available at: https://scotch.io/tutorials/create-a-mean-app-with-angular-2-and-docker-compose Although the application deploys successfully, we encounter an i ...

Retrieve the user ID using Google authentication within an Express application utilizing Passport.js

How can I retrieve the user.id after a user logs in? I have tried using a hard GET request in Postman (../api/users/829ug309hf032j) and it returns the desired user, but I'm unsure how to set the ID before making the GET request. In my app.component.t ...

Developing a TypeScript frontend library

I am currently in the process of creating a frontend library consisting of React components and CSS/SCSS. Specifically, I am looking for: To build a single CommonJS .js file and .css file. To exclude external libraries (e.g. React) from the .js output. ...

Ways to show a div when a dropdown option is selected

Currently, I am in the process of designing a form that includes a dropdown menu. Once the user selects a particular option from the list, such as: Software developer a new section will be displayed, showing two additional options: App Developer ...

Troubleshooting Vue and Typescript: Understanding why my computed property is not refreshing the view

I'm struggling to understand why my computed property isn't updating the view as expected. The computed property is meant to calculate the total price of my items by combining their individual prices, but it's only showing me the initial pri ...

Removing characters from a string in the C programming language

My task is to create a code that prompts the user to enter a word (maximum 30 letters), then delete all instances of "A," "a," "O," and "o" in the input and print it without any spaces. For example, if the input is "OkleaAo," the output should be "kle." I ...

Transform the object into an array of JSON with specified keys

Here is a sample object: { labels: ["city A", "city B"], data: ["Abc", "Bcd"] }; I am looking to transform the above object into an array of JSON like this: [ { labels: "city A", data: "Abc" }, { labels: "city B", data: "Bcd" }, ]; ...

Organize JSON objects by their keys using jQuery's .each() method

{ "staff": { "2010": [ { "first_name": "john", "last_name": "doe", }, { "first_name": "jane", "last_name": "doe", } ], "2012": [ ...

Using Protractor to wait for an asynchronous service call within the OnInit method of a component in order to test a specific value

I'm currently encountering an issue with Protractor while testing a Hello World service in my Angular2+ application that provides a value for an H1 tag. When I insert plain text into the H1 tag, I am able to test it successfully. However, when I use a ...

What is the best approach for defining variables in typescript?

Let's talk about creating a variable for a car: export class ICar { wheels: number; color: string; type: string; } So, which way is better to create the variable? Option one: const car = { wheels: 4, color: 'red', type: &apos ...