I'm attempting to call a function inside my HTML interpolation, like so. This HTML chunk is inside a *ngFor
loop.
<mat-list>
<mat-list-item *ngFor="let unit of units">
<div>
<p>Remaining Life</p>
<h2>{{ parseTimeRemaining(unit.daysRemaining) }}</h2>
</div>
</mat-list-item>
<mat-list>
parseTimeRemaining()
returns a string to be displayed, using the value of unit.daysRemaining
as a parameter.
public parseTimeRemaining(days: number){
const timeString = days + " Days";
return timeString;
}
Currently, my function returns undefined
and thus, an empty <h2>
element. Did I do something wrong? If so, what's the best way to display the information I need?
This could be a great opportunity to use a Pipe instead of a function. This helps to avoid calling a function within an *ngFor
which can have detrimental affects to performance. From the documentation surrounding pipes and change detection.
Angular picks a simpler, faster change detection algorithm when you use a pipe.
Angular has a built-in pipe, I18nPluralPipe which "Maps a value to a string that pluralizes the value according to locale rules.". You create an object (pluralMap) targeting specific numerical values and indicate the resulting string should be allowing to say 0 Days
, 1 Day
, or 99 days
.
pluralMap = {
'=0': '0 Days',
'=1': '1 Day',
'other': '# Days'
};
You would use it in a template as follows:
<ul>
<li *ngFor="let unit of units">{{ unit.daysRemaining | i18nPlural:pluralMap }}</li>
</ul>
Another approach would be to create a Custom Pipe. This would allow you implement custom formatting and/or validation logic against the provided daysRemaining
.
Pipe:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'daysRemaining'})
export class DaysRemainingPipe implements PipeTransform {
transform(days: number): string {
const timeString = days + " Days";
return timeString;
}
}
Module (registration):
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { DaysRemainingPipe } from './days-remaining.pipe';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent, DaysRemainingPipe ]
bootstrap: [ AppComponent ]
})
export class AppModule { }
Template:
<ul>
<li *ngFor="let unit of units">{{ unit.daysRemaining | daysRemaining }}</li>
</ul>
Taking it one step further, we could extend the I18nPluralPipe to pluralize the results within our custom pipe by extending the built in pipe and maybe check if the input is a valid number.
import { Pipe, PipeTransform } from '@angular/core';
import { I18nPluralPipe } from '@angular/common';
@Pipe({name: 'daysRemaining'})
export class DaysRemainingPipe extends I18nPluralPipe implements PipeTransform {
transform(days: number): string {
const safeDays = isNaN(days) ? 0 : days;
const pluralMap = {
'=0': '0 Days',
'=1': '1 Day',
'other': '# Days'
};
return super.transform(safeDays, pluralMap);
}
}
Here is an example in action.
Hopefully that helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With