Подтвердить что ты не робот

Вызов статической функции из шаблона angular2

Я пытаюсь построить сервисы (классы) "утилиты" для проекта angular. Классы полезности имеют статические функции (поэтому нам не нужно создавать ненужные объекты). Один из примеров:

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;
       }
   }
}

В моем файле класса компонентов я затем импортирую его так:

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

и внутри кода класса, как это работает:

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

Однако я хотел бы иметь возможность использовать эти служебные функции в шаблоне angular html, например:

<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">

К сожалению, это не работает; давая ошибку "Невозможно прочитать свойство" parseDate "из undefined".

Теперь я могу переместить функцию parseDate в класс компонента, и это отлично работает (с необходимым изменением в шаблоне, конечно)... однако, если у меня есть куча компонентов, они бы все должны иметь свою собственную функцию parseDate, и я думаю, что мы все знаем, что плохая идея, которая плохо масштабируется. (пожалуйста, игнорируйте тривиальный характер функции parseDate)

Кроме того, несмотря на то, что я действительно не хочу создавать экземпляр объекта только для запуска статической функции, я пробую его с фактической инъекцией зависимостей. Добавьте его в массив поставщиков и создайте экземпляр в конструкторе - например:

constructor(private _dateService: DateService) { }

а затем изменив мой шаблон на:

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">

Это также не удается, на этот раз с ошибкой "self.context._dateService.parseDate не является функцией". Удаление "статики" из функции устраняет проблему, и я могу двигаться дальше, но мне все еще нужно создавать что-то просто для запуска, что должно быть только статической функцией. Конечно, есть лучший способ.

Мысли?

4b9b3361

Ответ 1

Из представления могут вызываться только члены экземпляра класса компонентов.

Если вы хотите вызвать статические члены, вам необходимо предоставить getter в компоненте.

export class MyComponent {
  parseDate = DateService.parseDate;
}

то вы можете использовать его как

(input)="event.date=parseDate($event.target.value)"

Ответ 2

Ответ Gunter совершенно правдоподобен, и я делал это большую часть времени.

Если вы используете typescript, у вас также есть возможность создать пользовательский декоратор для предоставления функций вашему представлению, чтобы ваш компонент оставался незагроможденным.

Пример:

Определите декоратор:

import {StaticClassFunctions} from "./static-class-functions"

export function CustomDecorator(): Function {
    return (target: Function): Function => {
        target.prototype.yourStaticMethod = (param1) => {
            return StaticClassFunctions.yourStaticMethod(param1);
        }
    }
}

Примените декоратор к вашему компоненту:

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

Теперь у вас есть доступ к тем статическим функциям в вашем представлении, не объявляя их в своем компоненте! Очень полезно для повторяющихся функций "утилиты" для поддержки форматирования форматирования и таких (например, для перечисления перечислений!)

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

У вас не будет доступа к вашему компоненту, но если вы не объявите функцию сверху, чтобы она могла скомпилироваться.

Ответ 3

Вы можете объявить поле в своем компоненте, которое сделает класс доступным для вашего шаблона.

export class YourComponent {
    public DateService= DateService;
}

Ответ 4

Уже существует шаблон для этого в Angular под названием pipes. В Angular 1 это называлось filters.

В Angular вы создаете свой собственный класс труб и используете | в шаблоне для передачи значений. Существует встроенный для дат, он используется как:

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

Конечно, если этот трубок не делает то, что вы хотите, вы можете создать свой собственный:

@Pipe({
  name: 'myDate'
})
export class MyDate implements PipeTransform {

  transform(value: string): string {
    return new Date(value); 
  }
}

Для получения дополнительной информации см.: https://angular.io/docs/ts/latest/guide/pipes.html