p-marco
p-marco

Reputation: 59

Compare dates in Angular >11 with *ngIf

I would like to display some items only if their dates are newer than another date. So, on the component.ts i have:

constructor() { }
  currentDate = new Date();
  ngOnInit(): void {
  }

while I would like to cycle in component.html the relevant items from a list:

<div *ngFor="let item of itemList">
  <div *ngIf="(item.startDate | date:'yyyy-MM-dd' > currentDate | date:'yyyy-MM-dd')">
    {{item.text}}
  </div>
</div>

But unfortunately I am not able to display these data.

Could you please address me on the right direction? Thanks in advance

Upvotes: 1

Views: 2068

Answers (2)

Owen Kelvin
Owen Kelvin

Reputation: 15083

From how you have stated the problem, it looks like you are only interested in items whose date are greater than a specific date. I would approach it this way

Approach 1

  1. Generate a new property
  constructor() { }
  itemList = [...];
  currentDate = new Date();
  newItemList = this.itemList.filter(({ startDate }) => new Date(startDate) > this.currentDate)
  ngOnInit(): void {
  
  }
  1. Change html
<div *ngFor="let item of newItemList">
  {{item.text}}
</div>

Approach 2

  1. Create a new property isGreaterThanToday
  constructor() { }
  currentDate = new Date();
  itemList = [...].map(x => ({
    ...x, 
    isGreaterThanToday:  new Date(x.startDate) > this.currentDate
   }));
  
  ngOnInit(): void {
  
  }
  1. In the html
<div *ngFor="let item of itemList">
  <div *ngIf="item.isGreaterThanToday">
    {{item.text}}
  </div>
</div>

Implementing a toggle of items

The simplest way to implement this would be to have another property say showAll that can be used to toggle, something like

<label>Show All <input type="checkbox" [(ngModel)]="showAll"/></label>
<div *ngFor="let item of itemList">
  <div *ngIf="item.isGreaterThanToday || showAll">
    {{item.text}}
  </div>
</div>

See this demo

Reactive Programming

With reactive programming we can modify approach 1 above. This would be the best approach to use for performance as it makes it easier to implement ChangeDetectionStrategy.OnPush

In your TS file you would need to convert your variables to Observables and react to changes

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

And in your html

<label
  >Show All
  <input
    type="checkbox"
    [(ngModel)]="showAll"
    (ngModelChange)="showAllSubject$.next(showAll)"
/></label>

<div *ngFor="let item of itemListFiltered$ | async">
  {{item.text}}
</div>

Below is a demo

Upvotes: 1

Abdu Manas C A
Abdu Manas C A

Reputation: 1149

If the startDate is a Date object, I would do something like this. Create a function in the component

   function isDateStartingAfterToday(startDate) {
      return startDate.getFullYear() > this.currentDate.getFullYear() &&
        startDate.getDate() > this.currentDate.getDate() &&
        startDate.getMonth() > this.currentDate.getMonth();
    }

and execute this component in ngIf

*ngIf="isDateStartingAfterToday(item.startDate)"

Upvotes: 0

Related Questions