Checking if a value exists in an array using *ngIf

I'm just starting to learn Ionic and Angular, so I'm hoping someone can provide some guidance.

Here is the data I have:

"messages" : [ 
        {
            "sender" : "24",
            "name" : "James",
            "datetime" : ISODate("2019-11-10T20:42:02.090Z"),
            "message" : "test 1",
            "read" : [ 
                {
                    "uid" : "24",
                    "name" : "James",
                    "datetime" : ISODate("2019-11-10T20:42:02.090Z")
                },
                {
                    "uid" : "45",
                    "name" : "Paul",
                    "datetime" : ISODate("2019-11-13T11:32:45.010Z")
                }
            ]
        }]

In my Ionic setup, I currently pass this data as 'mailbox' and 'uid' represents the user's ID.

<ion-item *ngFor="let message of mailbox">
    <ion-item [routerLink]="['/members/mailbox', message.sid" routerDirection="forward">
        {{ message.name}}
        <br />Posted: {{ message.datetime }}
        <div *ngIf="(message.read[0]['uid'] == uid || message.read[1]['uid'] == uid)">READ</div>
    </ion-item>
</ion-item>

I'm looking for a more efficient way to write the ngIf condition since messages.read can have multiple entries. Is there a way to simply check if the 'uid' value exists in messages.read? I tried using Angular filter contains without success.

Thank you!

Answer №1

It's more efficient to delegate the hard work to the .ts file.

You can implement something similar to this;

within your .ts file;

validateId(message: Object) {
    return message["read"].find(x => x.uid === uid);
  }

and in .html;

<ion-item *ngFor="let message of mailbox">
            <ion-item [routerLink]="['/members/mailbox', message.sid" routerDirection="forward">
                {{ message.name}}
                <br />Posted: {{ message.datetime }}
                <div *ngIf="validateId(message)">READ</div>
            </ion-item>
        </ion-item>

Answer №2

To achieve this functionality, you can use the following code snippet:

let isUidPresent = messages.read.findIndex(reader => reader.uid === uid) > -1

After implementing the above logic, make sure to add the following line in your HTML file:

*ngIf="isUidPresent"

Answer №3

Develop and utilize a personalized pipeline with parameters.

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
    name: 'in'
})
export class InPipe implements PipeTransform {

    transform(value, array:any[]) : boolean {
        return array.indexOf(value) != -1;
    }

}

@Pipe({
  name: 'map'
})
export class MapPipe implements PipeTransform {

  transform(array: any[], mapFn):array {
    return array.map(filterFn);
  }

}

Your *.component.ts:

...
_mapFn(read):string{
  return read['uuid'];
}
mapFn = _mapFn.bind(this);
...

Your template:

<div *ngIf="(message.read[0]['uid'] == uid
<div *ngIf="uuid|in:(message.read|map:mapFn)">...</div>

Note: If you implement it in the template like:

message.read.map((read) => return read['uuid'];).indexOf(uuid) != -1;
then angular will call both functions in every change detection process. That would be very bad and slow down your application every time. This is why you need to write pipes. With pipes angular only call the functions when reference of objects (uuid, message.read) change.

Answer №4

In reference to the approved solution, it is recommended to avoid calling a function in the template as it will trigger on each change detection, which can lead to significant performance overhead, especially within an ngFor loop. If your data set is small and there are not many other activities happening on the page, using a function in the template may be acceptable. However, I prefer to minimize this approach whenever possible :)

If my understanding of your data structure is correct, there can only be one instance of a READ match in the array per user, as a user cannot mark a message as read more than once. In that case, you could implement a nested ngFor loop, utilizing ng-container to prevent unnecessary element creation in the template when not needed.

Therefore, I would suggest the following:

<ion-item *ngFor="let message of mailbox">
  <ion-item >
    {{ message.name}}
    <br />Posted: {{ message.datetime }}
    <ng-container *ngFor="let r of message.read">
      <div *ngIf="r.uid === uid">READ</div>
    </ng-container>
  </ion-item>
</ion-item>

Answer №5

This question pertains to JavaScript, not Angular. However, if you're looking for a solution, you can use the following code:

*ngIf="message.read.filter(x => x.uid === uid).length > 0"

Answer №6

To determine if a letter has been read, you can create a variable to store this information and then check if the `uid` is in your `mailbox` array:

Sample code from your.component.ts:

isLetterRead = false;
uid;

getEmails() {
    this.webAPI.getEmails().subscribe(response => {
        this.mailbox = response;
        isLetterRead = response.read.some(r => r.uid == uid);
    })

}

HTML implementation:

<ion-item *ngFor="let message of mailbox">
     <!-- Omitted code for brevity -->
     <div *ngIf="isLetterRead">READ</div>
</ion-item>

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

Enhance the performance of your React/NextJS app by controlling the rendering of a component and focusing on updating

I'm facing an issue with my NextJS application that showcases a list of audio tracks using an <AudioTrackEntry> component. This component receives props like the Track Title and a Link to the audio file from an external data source. Within the ...

Remove the lesser of two duplicate items from the list by comparing their count keys

Here is a challenge I encountered with a grocery list that required filtering out duplicates and only keeping the duplicate with the higher count, while also retaining non-duplicate items. I managed to achieve this through trial and error programming, bu ...

What measures can be taken to stop an event from being triggered from an external source?

Consider a scenario where there is a simple counting process functioning as a default Node EventEmitter: import {EventEmitter} from 'events'; async function sleep(milliseconds: number): Promise<void> { return new Promise((resolve) => ...

Using Typescript with React functional components: the proper way to invoke a child method from a parent function

My current setup is quite simple: <Page> <Modal> <Form /> </Modal> </Page> All components mentioned are functional components. Within <Modal />, there is a close function defined like this: const close = () => ...

Control the transparency of the initial parent div that includes an *ngFor loop

I want to add opacity only to the first div which contains an icon and a heading in another nested div. The second div should remain fully visible (opacity: 1). Here is the HTML structure: <div class="row clearfix"> <div class="col-lg-3 col- ...

I am looking to append a new string to an existing string array

Within my class, I have a private variable which is a string array with 100 elements. private String[] stringArray = new String[100] There is also a method in the same class that looks like this: public void addString (String addedString) {} The goal i ...

Leveraging d3.js for Visualizations in an Angular2/Node/Express/MongoDB Application

I’m working on integrating d3.js (https://www.npmjs.com/package/d3) into my project, and upon loading the page, I encounter a ZoneAwareError. After executing npm install d3 --save, all dependencies were successfully installed. Although I followed the gui ...

Why bother with creating mappers to transform entity-to-DTOs?

There are classes referred to as 'mappers' that are utilized by some individuals for converting DTOs to entities or vice versa. What benefits do I stand to gain from employing this technique during backend development? I am keen on delving deepe ...

Angular: Datepipe displays '01/01/0001' for NULL data retrieved from Database

When utilizing the DatePipe, does Angular automatically bind '01/01/0001' if we attempt to bind a NULL date value from the database? ...

Looking to utilize custom toolbars with apexcharts for enhanced functionality

Recently, I integrated apexcharts into my new app and the chart is functioning properly. However, I encountered an issue when trying to add a custom toolbar similar to a sidebar with charts. After implementing the UI for it, I now need to make the icons fu ...

Utilizing Prisma's Create Object to Store Return String from Imported Function in Database

In my application, I am utilizing Typescript and have created a test to populate a database using Prisma ORM. Within this test, there is a function that returns a string: const mappingPayload = (data: any) => { let pay = [] const payload = data[0] // ...

Using *ngIf to display a dropdown menu

How can I utilize the *Ngif directive to display a dropdown and conceal another one based on the input of a checkbox? Basically, if the checkbox is checked, display one dropdown, otherwise display the other. <div class="test"> <div class="te ...

Another option to avoid using complicated else if chains

I'm facing a challenge with a function that returns a value known as user_id. It involves multiple conditions that need to be checked. First condition: Verify the service variable Second condition: If not found, retrieve user_id from local storage ...

Adjusting table to include hashed passwords for migration

How can I convert a string password into a hash during migration? I've tried using the following code, but it seems the transaction completes after the selection: const users = await queryRunner.query('SELECT * FROM app_user;'); user ...

Why does the Angular asyncScheduler test fail when using flush()?

Consider this Angular component: import { Component, OnDestroy, OnInit } from '@angular/core'; import { asyncScheduler, Observable, of, queueScheduler, scheduled } from 'rxjs'; @Component({ selector: 'test-component', te ...

Clear function of signature pad not working inside Bootstrap modal dialogue box

Currently, I'm working on implementing a signature pad dialogue box using Bootstrap modal. When the user clicks on the "Complete Activity" button, a dialog box should pop up with options for yes or no. If the user selects yes, another dialog box shoul ...

What could be causing the Google Sign-In functionality to fail in an Angular web application?

I'm currently working on implementing Google sign-in for my web app. I've been following this tutorial here. However, I'm facing an issue where the Google sign-in button is not appearing. I would like the authentication to happen at http://l ...

Tips for importing libraries in a web-worker with TypeScript

In order to load extension-like code in a web worker and import external libraries, I am facing an issue with the typescript compiler not generating valid code for the web worker. My current workaround involves constructing the Worker with type module so ...

Within Angular, the Subscribe function is invoked after all other methods in the component have been executed. Consequently, this sequence of events often prevents me from effectively utilizing the response data

Struggling with implementing await and async in TypeScript, especially as a beginner. Below is how I attempted to use them: async refreshList(){ await this.service.refreshList().subscribe(res => { console.log(res); this.service.todoListModel=res; ...

The attribute 'X' is not present in the specified type 'IntrinsicAttributes & InferPropsInner'

I've been restructuring my code from a .js file to a .tsx file, as seen below: import React, { useEffect, useState } from 'react' import PropTypes from 'prop-types' import { checkMobile } from '../../utils/common' import ...