#angular #date #components #angular-module
Вопрос:
Я хотел бы отображать некоторые элементы только в том случае, если их даты новее другой даты. Итак, на component.ts
то, что у меня есть:
constructor() { }
currentDate = new Date();
ngOnInit(): void {
}
в то время как я хотел бы component.html
перечислить соответствующие пункты из списка:
<div *ngFor="let item of itemList">
<div *ngIf="(item.startDate | date:'yyyy-MM-dd' > currentDate | date:'yyyy-MM-dd')">
{{item.text}}
</div>
</div>
Но, к сожалению, я не могу отобразить эти данные.
Не могли бы вы, пожалуйста, обратиться ко мне в правильном направлении? Заранее спасибо
Ответ №1:
Судя по тому, как вы сформулировали проблему, похоже, что вас интересуют только предметы, дата которых больше определенной даты. Я бы подошел к этому так
Подход 1
- Создайте новое свойство
constructor() { }
itemList = [...];
currentDate = new Date();
newItemList = this.itemList.filter(({ startDate }) => new Date(startDate) > this.currentDate)
ngOnInit(): void {
}
- Изменить html
<div *ngFor="let item of newItemList">
{{item.text}}
</div>
Подход 2
- Создайте новое свойство
isGreaterThanToday
constructor() { }
currentDate = new Date();
itemList = [...].map(x => ({
...x,
isGreaterThanToday: new Date(x.startDate) > this.currentDate
}));
ngOnInit(): void {
}
- В html
<div *ngFor="let item of itemList">
<div *ngIf="item.isGreaterThanToday">
{{item.text}}
</div>
</div>
Реализация переключения элементов
Самый простой способ реализовать это-иметь другое свойство, showAll
которое можно использовать для переключения, что-то вроде
<label>Show All <input type="checkbox" [(ngModel)]="showAll"/></label>
<div *ngFor="let item of itemList">
<div *ngIf="item.isGreaterThanToday || showAll">
{{item.text}}
</div>
</div>
Реактивное программирование
С помощью реактивного программирования мы можем изменить подход 1 выше. Это был бы наилучший подход для повышения производительности, поскольку он упрощает реализацию ChangeDetectionStrategy.OnPush
В вашем файле TS вам нужно будет преобразовать ваши переменные в наблюдаемые и реагировать на изменения
constructor() {}
showAllSubject$ = new BehaviorSubject(false);
itemList = [
{ startDate: "2000-01-01", text: "Some past event 3" } ...
];
itemList$ = of(this.itemList);
itemListFiltered$ = combineLatest([
this.itemList$,
this.showAllSubject$
]).pipe(
map(([itemList, showAll]) =>
showAll
? itemList
: itemList.filter(
({ startDate }) => new Date(startDate) > this.currentDate
)
)
);
currentDate = new Date();
showAll = false;
ngOnInit(): void {}
И в вашем html
<label
>Show All
<input
type="checkbox"
[(ngModel)]="showAll"
(ngModelChange)="showAllSubject$.next(showAll)"
/></label>
<div *ngFor="let item of itemListFiltered$ | async">
{{item.text}}
</div>
Комментарии:
1. спасибо, это чистый подход. дело в том, что как я мог бы реализовать это, если
itemList
это файл JSON? Кроме того, подход к функциям html, несмотря на проблемы с производительностью, как указано ниже, кажется мне более многоразовым, если я не ошибаюсь, например, если нам приходится иметь дело с несколькими файлами JSON. Поправьте меня, если я ошибаюсь, я здесь, чтобы учиться 🙂 Правка: Я попробовал подход 1, он работает! Большое спасибо!2. Просто краткое примечание: мне кажется, что это должно быть
<div *ngIf="item.isGreaterThanToday">{{item.text}}</div>
правильно?3. Да, использование функций очень полезно, если вам нужно добавить возможность повторного использования. Фрагменты кода могут быть перемещены в функцию в любом коде. Просто старайтесь избегать выполнения функций в html
4. Как вы думаете, можно ли реализовать подход 2 в поведении, управляемом пользователем, например, с помощью кнопки, инкапсулирующей *ngIf внутри метода onClick?
5. Какого поведения вы пытаетесь добиться?
Ответ №2:
Если дата начала является объектом Даты, я бы сделал что-то подобное. Создайте функцию в компоненте
function isDateStartingAfterToday(startDate) {
return startDate.getFullYear() > this.currentDate.getFullYear() amp;amp;
startDate.getDate() > this.currentDate.getDate() amp;amp;
startDate.getMonth() > this.currentDate.getMonth();
}
и выполните этот компонент в ngIf
*ngIf="isDateStartingAfterToday(item.startDate)"
Комментарии:
1. Наличие функций в вашем html может привести к проблемам с производительностью, поскольку функции выполняются каждый раз, когда происходит какое-либо изменение, например, нажатие несвязанной кнопки приведет к запуску функции
2. Да, это правда, но, насколько я понимаю, даже если мы создадим выражение и передадим его в ngIf, оно все равно будет выполняться всякий раз, когда происходит изменение, верно? Таким образом, по крайней мере, мы можем сохранить логику за пределами HTML