Я вызываю API C#, который возвращает следующие типы в мое приложение Angular.
export interface Auction {
reservePrice: number
currentHighBid: number
auctionEnd: string
id: string
}
Я создал компонент AuctionListComponent, который ngFor выводит на экран список аукционов, и в этот список я хочу добавить таймеры обратного отсчета. Поэтому я создал для этого еще один компонент под названием TimerComponent. Родительский компонент передает дочернему элементу дату в формате UTC. Дочернему компоненту таймера требуется тип числа для работы таймера обратного отсчета ngx. Я не профессионал в Angular, так что я упускаю что-то простое?
Я также просмотрел подобные вопросы и не помог мне. аналогичный вопрос
Ссылка на страницу nxg-countdown
(Родительский) AuctionListComponent.html
<div class = "m-3" *ngFor = "let auction of auctions">
<p class = "card-text">
End Date: {{ auction.auctionEnd | date }}
</p>
<app-timer [childTimer] = "auction.auctionEnd"></app-timer>
</div>
(Дочерний) TimerComponent.html
<p>
From the parent: <b>{{ childTimer | date : 'MM d, y, h:mm:ss a' }}</b>
UTC: <b>{{ childTimer }}</b>
</p>
<p>ngx-countdown Counter</p>
<countdown [config] = "config"> </countdown>
ТаймерКомпонент.TS
import { Component, Input } from '@angular/core';
import { CountdownConfig, CountdownEvent } from 'ngx-countdown';
@Component({
selector: 'app-timer',
templateUrl: './timer.component.html',
styleUrl: './timer.component.scss'
})
export class TimerComponent {
@Input() childTimer: string = ''; //This doesn't work because it's the wrong type
@Input() childTimer: any; //This compiles and give an error
//ERROR Error: Unable to convert "Invalid Date" into a date
config: CountdownConfig = { leftTime: this.childTimer, format: 'd:H:M:ss'};
}



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Согласно документации ngx-countdown, параметр leftTime должен быть числом.
Поэтому, если вы преобразуете childTimer в число, создав экземпляр переменной конфигурации, он должен работать правильно.
ngx-countdown ожидает, что leftTime будет числом, обозначающим оставшиеся секунды. Итак, чтобы это заработало, вам нужно найти разницу между auctionEnd, которая является строкой UTC, и текущей датой, и преобразовать ее в секунды.
Вот как ваш компонент может это сделать:
export class TimerComponent {
config: CountdownConfig = {
leftTime: 0,
format: 'd:H:M:ss'
};
// Turn this into a setter so it updates the config if input changes
// make sure you use ChangeDetectionStrategy.OnPush to avoid redundant updates
// or change this as you wish
@Input() set childTimer(utcDate: string) {
this.config = {
...this.config,
leftTime: this.calculateSecondsLeft(utcDate)
};
}
private calculateSecondsLeft(utcDate: string): number {
// Both `parse` and `now` return a timestamp
const diff = Date.parse(utcDate) - Date.now();
return diff / 1000;
}
}
Обновлять
Я покопался в документации ngx-countdown и в конфигурации есть опция stopTime, которая делает ее еще проще, поскольку она принимает «время окончания» в качестве отметки времени, поэтому пример можно упростить до:
export class TimerComponent {
config: CountdownConfig = {
format: 'd:H:M:ss'
};
@Input() set childTimer(utcDate: string) {
this.config = {
...this.config,
stopTime: Date.parse(utcDate)
};
}
}
Что касается d в формате, показывающем 1, когда timeLeft > 24 часов. Кажется, библиотека использует форматирование даты, а данные больше похожи на Duration. Когда вычисляется diff, это дата относительно Jan 1 1970, а d — это «день месяца», поэтому отображается 1. Лучше объяснить здесь. Поскольку мы не можем вычесть 1 день из Jan 1 1970, нет простого решения, которое могло бы обрабатывать високосные дни и другие крайние случаи, связанные с датой.
Вот пример того, как вы можете добавить собственный форматтер через конфигурацию formatDate и intervalToDuration из библиотеки date-fns:
config: CountdownConfig = {
formatDate: ({ date }) => {
const { days, hours, minutes, seconds } = intervalToDuration({
start: 0,
end: date
});
return `${days ?? 0}:${hours ?? 0}:${minutes ?? 0}:${seconds ?? 0}`;
},
};
Поэтому, когда я установил свой код на то, что у вас есть выше. В leftTime: this.calcSecLeft есть ошибка: Type 'number' is not assignable to type 'string'
О, я оставил там неправильное начальное значение, и для него не было типа, попробуйте начать с 0 в качестве leftTime, я обновил ответ
оба ответа работают отлично! Мне просто интересно, почему, когда счетчик получает уже наступившую дату, он показывает: 1:0:1:00, а не 0:0:0:00. Есть идеи? предположим, что 1:0:1:00 — это 1 января 1970 года.
@whisk библиотека не очень хорошо с этим справляется, к сожалению, я обновил ответ некоторой информацией, включая ссылку на соответствующую проблему и возможное решение.
Можете ли вы привести пример?