Is it considered bad form to utilize nearly identical for loops in two separate instances within Angular 6?

I am working on creating two lists for a roster.

The first list will display the current members of this year, while the second list will show if individuals have been excused for this year.

After analyzing my code, I realized that I am using two identical for loops, one to display all true Boolean values and another for false. Is there a more efficient way (a method perhaps) to showcase people who are both excused and not excused?

<h2>Roster {{year-1}}-{{year}}</h2>

<div *ngFor="let k of peoples">
  <div *ngFor="let a of k.people; let j = index">
    <div *ngIf="k.year == year && k.people[j].excused == false">
      {{k.people[j].firstName}} {{k.people[j].lastName}}
    </div>
  </div>
</div>

<h2>Excused</h2>

<div *ngFor="let k of peoples">
  <div *ngFor="let a of k.people; let j = index">
    <div *ngIf="k.year == year && k.people[j].excused == true">
      {{k.people[j].firstName}} {{k.people[j].lastName}}
    </div>
  </div>
</div>

Answer №1

Opting for this approach instead of adding an additional *ngIf would be more efficient.

It is suggested in the comments to create separate arrays for data within the component and perform the filtering operation after data updates. However, considering the unknown context of usage, this seems like a more suitable solution. It is advisable to avoid using *ngIf by filtering the data directly in the array to prevent unnecessary workload on another structural directive in the template. This will always result in performance advantages.

In your component, you can define a filter function:

getExcused(isExcused: boolean) {
    return this.peoples
        .filter(person => person.year === this.year)
        .map(person => person.people)
        .filter(p => p.excused === isExcused);
}

Then in the template:

<h2>Roster {{year-1}}-{{year}}</h2>
<div *ngFor="let individual of getExcused(false)">
    {{ individual.firstName }} {{ individual.lastName }}
</div>
<h2>Excused</h2>
<div *ngFor="let person of getExcused(true)">
    {{ person.firstName }} {{ person.lastName }}
</div>

If your component utilizes the change detection strategy on push, it should not pose any performance issues.

Answer №2

Perhaps I may be mistaken, but isn't using a pipe the recommended approach for this situation? Alternatively, you could even chain two pipes!

<div *ngFor="let k of peoples| yearPipe: year | excusedPipe: no">

      {{k.people[j].firstName}} {{k.people[j].lastName}}

</div>

<h2>Excused</h2>

<div *ngFor="let k of peoples| yearPipe: year | excusedPipe: yes">

      {{k.people[j].firstName}} {{k.people[j].lastName}}

</div>

@Pipe({ name: 'yearPipe' })
export class YearPipe implements PipeTransform {
  transform(allPeople: People[], year: string) {
    return allPeople.filter(person => person.year == parseInt(year));
  }
}

@Pipe({ name: 'excusedPipe' })
export class ExcusedPipe implements PipeTransform {
  transform(allPeople: People[], excused: string) {
    if (excused === 'yes'){
       return allPeople.filter(person => person.excused);
    }else{
       return allPeople.filter(person => !person.excused);
    }
  }
}

The only tricky aspect is that the parameter for the pipe always needs to be a string, as per the documentation found on Angular.io.

Edit: Check out this stackblitz example (Chained Pipes example): https://stackblitz.com/edit/angular-rb5vmu

Answer №3

When it comes to structuring your code, the choice is yours. However, if you want to avoid complications, you might consider implementing something along these lines:

html

<div *ngfor="let exused of isExcused(true)">
  {{excused.firstName}} {{excused.lastName}}
</div>

<div *ngfor="let exused of isExcused(false)">
  {{excused.firstName}} {{excused.lastName}}
</div>

ts

isExcused(excused) {
  let arr = [];
  for (let i = 0; i < this.peoples.length; i++) {
    if(peoples[i].year === this.year) {
      for (let j = 0; j < this.peoples[i]people.length; j++) {
        if (peoples[i].people[j].excused === excused) {
          arr.push(peoples[i].people[j]);
        }
      }
    }
  }
  return arr;
}

However, this solution may not be the most elegant. It would be better to structure your code like this:

html

<div *ngfor="let exused of excusedList">
  {{excused.firstName}} {{excused.lastName}}
</div>

<div *ngfor="let unexcused of unexcusedList">
  {{unexcused.firstName}} {{unexcused.lastName}}
</div>

ts

ngOnInit() {
  this.excusedList = isExcused(true);
  this.unexcusedList = isExcused(false);
}

Since it seems that your lists won't update dynamically. You could also consider using methods like .forEach() or .filter instead of traditional for loops to improve the readability of your code.

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

The columns in the table are all displaying varying widths even though they have been defined with fixed table layout

I have a nested table displayed in my HTML, and I am attempting to set each column to be 50% width, but for some reason it's not working. In the past, whenever I've needed to accomplish this, applying table-layout: fixed has usually done the tri ...

Generate a dynamic key object in Angular/TypeScript

I am working with an object called "config" and an id named "id". My goal is to create an array of objects structured like this: [ "id" : { "config1: ... "config2: ... "config3: ... } "id2" : { "config ...

What is the best way to transform a JSON data-storing object into an array within Angular?

I am currently working on developing a machine learning model using tensorflow.js, but I have encountered a roadblock. The issue I am facing is that I have stored my JSON content in a local object, but for it to be usable in a machine learning model, I ne ...

Tips for fixing a GET 404 (not found) error in a MEAN stack application

While working on a profile page, I encountered an error when trying to fetch user details of the logged-in user: GET http://localhost:3000/users/undefined 404 (Not Found) error_handler.js:54 EXCEPTION: Response with status: 404 Not Found for URL: http:// ...

Encountering an issue with creating an App Runner on AWS CDK

Attempting to deploy my application using App Runner within AWS via CDK. Utilizing the reference from https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-apprunner.Service.html. Upon deployment, encountering the following error: create_failed: R ...

Unleashing the potential of an endless animation by incorporating pauses between each iteration

I am trying to create an infinite animation using animate css but I want to add a delay between each iteration. After exploring various options, I first attempted to achieve this using plain JavaScript. Here is the HTML snippet: <div id="item" class= ...

Adding a class to a child component layout from a parent component in Angular 12 and Typescript can be achieved by using the ViewChild decorator

Incorporating the child component into the parent component is an important step in the structure of my project. The dashboard component serves as the child element, while the preview component acts as the parent. Within the parent (preview) component.htm ...

The type 'Observable<any>' cannot be assigned to the type 'Observable<T>'

Here is the code I am working with: import {HttpClient} from '@ngular/common/http'; private httpClient: HttpClient; do_request(method: string, url: string, ...

Executing a HTTP POST request using a dialog component

In my component, list, I am displaying title names from an external API: https://i.sstatic.net/mA1MR.png The image above shows a fab-button labeled Add. When this button is clicked, it triggers a dialog window (component named add-customer) like so: htt ...

Building a Dynamic Checkbox Validation Feature in Angular Using Data retrieved from an API

Currently, I have a function that retrieves and displays a list obtained from an API: displayEventTicketDetails() { this.Service .getEventTicketDetails().subscribe((data: any) => { this.eventTicketDetails = data.map(ticket => ticket. ...

Utilize multiple validators.patterns within a single value for enhanced data validation

I need to implement two different patterns for the formControlName='value' based on the type selected. If type is 'A', I want to use the valuePattern, and if type is 'B', I want to use the uname pattern. This is my HTML code: ...

Encountered an issue: The type 'Usersinterface' is not meeting the document constraints

Below is a screenshot displaying an error: https://i.stack.imgur.com/VYzT1.png The code for the usersinterface is as follows: export class Usersinterface { readonly username: string; readonly password: string; } Next, here is the code for users ...

Is the Inline Partial<T> object still throwing errors about a missing field?

I recently updated to TypeScript version ~3.1.6 and defined an interface called Shop as follows: export interface Shop { readonly displayName: string; name: string; city: string; } In this interface, the property displayName is set by the backend a ...

Course completed following the module

As a newcomer to Angular, I am facing an issue with saving data in a class and reading it into a component. It seems that the component is rushing to display results before the class has finished processing them, resulting in an error message being printed ...

Show a Toast in React without relying on useEffect to manage the state

I have successfully implemented the Toast functionality from react-bootstrap into my application using the provided code. However, I am unsure if it is necessary to utilize useEffect to set show with setShow(items.length > 0);. Would it be simpler to ...

I am sorry, but it seems like there is an issue with the definition of global in

I have a requirement to transform an XML String into JSON in order to retrieve user details. The approach I am taking involves utilizing the xml2js library. Here is my TypeScript code: typescript.ts sendXML(){ console.log("Inside sendXML method") ...

Utilize @agm/core in Angular 6 to load Google Maps by first retrieving latitude and longitude data from the server

I am currently developing a project in Angular6 that involves utilizing the "AGM - Angular Google Maps" library for mapping functionalities. One of the requirements is to dynamically draw the map based on latitude and longitude data fetched from the serve ...

Typescript - Specifying the return type for a deeply nested object

I have a container that holds multiple sub-containers, each containing key-value pairs where the value is a URL. I also have a function that takes the name of one of the sub-containers as input, loops through its entries, fetches data from the URLs, and re ...

Error: The identifier HTMLVideoElement has not been declared

Encountering an issue while attempting to build my Angular 9 Universal project for SSR: /Users/my-project/dist/server.js:28676 Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__metadata"])("design:type", HTMLVideoElement) ReferenceError: HTMLVideoElem ...

Exploring Angular's Subcomponents

While working on my application, I encountered a dilemma. I currently pass data from the main component to the subcomponents after pulling it from the API with a single request. Should I continue with this approach or have each component make its own separ ...