Call a static function from angular2 template

I am trying to build utilities services (classes) for an angular project. Utility classes have static functions (so we don’t need to create unnecessary objects). One example:

import { Injectable } from '@angular/core'; @Injectable() export class DateService { constructor() { } public static parseDate(dateString: string): Date { if (dateString) { return new Date(dateString); } else { return null; } } } 

In my component class file, I then import it like this:

 import { DateService } from '../utilities/date.service'; 

and inside the class code, how it works:

 ngOnInit():void { let temp = DateService.parseDate("2012/07/30"); console.log(temp); // Mon Jul 30 2012 00:00:00 GMT-0500 (Central Daylight Time) } 

However, I would like to be able to use these utility functions in an angular html template, for example:

 <label for="date">Date</label> <input type="date" class="form-control" id="date" required [value]="event.date | date: 'yyyy-MM-dd'" (input)="event.date=DateService.parseDate($event.target.value)" name="date"> 

Unfortunately, this does not work; giving the error "Unable to read property" parseDate "from undefined".

Now I can move the parseDate function to the component class, and this works fine (with the necessary change in the template, of course) ... however, if I have a bunch of components, they would all have their own parseDate function, and I think that we all know that a bad idea that does not scale well. (please ignore the trivial nature of the parseDate function)

Also, although I really don't want to instantiate an object just to run a static function, I try it with the actual dependency injection. Add it to the providers array and create an instance in the constructor - for example:

 constructor(private _dateService: DateService) { } 

and then changing my template to:

 label for="date">Date</label> <input type="date" class="form-control" id="date" required [value]="event.date | date: 'yyyy-MM-dd'" (input)="event.date=_dateService.parseDate($event.target.value)" name="date"> 

This also fails, this time with the error "self.context._dateService.parseDate is not a function". Removing the “statics” from the function fixes the problem, and I can move on, but I still need to create something just to run, which should only be a static function. Of course, there is a better way.

Thoughts?

+13
angular
source share
4 answers

Only members of an instance of a component class can be called from a view.

If you want to call static members, you need to provide a getter in the component.

 export class MyComponent { parseDate = DateService.parseDate; } 

then you can use it as

 (input)="event.date=parseDate($event.target.value)" 
+19
source share

Gunter's answer is perfectly plausible, and I did this most of the time.

If you use typescript, you also have the option of creating a custom decorator to provide functions to your view so that your component remains uncluttered.

Example:

Define a decorator:

 import {StaticClassFunctions} from "./static-class-functions" export function CustomDecorator(): Function { return (target: Function): Function => { target.prototype.yourStaticMethod = (param1) => { return StaticClassFunctions.yourStaticMethod(param1); } } } 

Apply a decorator to your component:

 @Component{ ... } @CustomDecorator() export class YourComponent { ... } 

Now you have access to those static functions in your view without declaring them in your component! Very useful for repetitive functions of the "utility" to support formatting formatting and such (for example, to list enumerations!)

 <span>{{yourStaticMethod(yourInput)}}</span> 

You will not have access to your component, but if you do not declare a function from above so that it can compile.

+6
source share

You can declare a field in your component that will make the class available to your template.

 export class YourComponent { public DateService= DateService; } 
+5
source share

There is already a template for this in Angular called pipes . In Angular 1, it was called filters .

In Angular, you create your own pipe class and use | in a template for passing values. There is a built-in for dates, it is used as:

 {{ "2017-01-24" | date }} 

Of course, if this handset does not do what you want, you can create your own:

 @Pipe({ name: 'myDate' }) export class MyDate implements PipeTransform { transform(value: string): string { return new Date(value); } } 

For more information see: https://angular.io/docs/ts/latest/guide/pipes.html

+4
source share

All Articles