Сравните даты в Angular >11 с *ngIf

#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

  1. Создайте новое свойство
   constructor() { }
  itemList = [...];
  currentDate = new Date();
  newItemList = this.itemList.filter(({ startDate }) => new Date(startDate) > this.currentDate)
  ngOnInit(): void {
  
  }
 
  1. Изменить html
 <div *ngFor="let item of newItemList">
  {{item.text}}
</div>
 

Подход 2

  1. Создайте новое свойство isGreaterThanToday
   constructor() { }
  currentDate = new Date();
  itemList = [...].map(x => ({
    ...x, 
    isGreaterThanToday:  new Date(x.startDate) > this.currentDate
   }));
  
  ngOnInit(): void {
  
  }
 
  1. В 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