1

I have a page with a NgbDatepicker with a custom dayTemplate to customize styles e show some other informations about each day:

enter image description here

It looks pretty good but it is extremely slow, after some minutes the page starts freezing!

I'm quite new on Angular 7 and NgBootstrap, ther's something that I could do to improve the performance of the component?

Seems that the NgbDatepicker redraw everything after every iteration with the date picker, also mouse over. This behavior can be disabled?

You can check the demo on stackblitz to see what I'm talking about. I don't know why, but locally is 10 times slower (also running the compiled version production mode). I put a console.log(calendarColor[0]); at line 110 to show the iteration that I'm talking and with this line it's a bit slower. Also keeping de Chrome Dev tools closed the page freeze after some minutes on the page.

COMPONENT:

  formatDate(date: NgbDate): string {
    const month = `0${date.month}`.slice(-2);
    const day = `0${date.day}`.slice(-2);
    return `${date.year}-${month}-${day}`;
  }

  getDayCalendarColor(date: NgbDate): CalendarColor {
    const calendarColor = this.calendarColors.filter(cC => {
      return cC.date === this.formatDate(date);
    });
    if (!calendarColor.length) {
      return;
    }
    console.log(calendarColor[0]);
    return calendarColor[0];
  }

  cssCustomDay(date: NgbDate): string {
    const cssApartmentSeasonType = this.cssApartmentSeasonType(date);
    const cssCalendarType = this.cssCalendarType(date);
    return cssApartmentSeasonType + ' ' + cssCalendarType;
  }

  cssApartmentSeasonType(date: NgbDate): string {
    const calendarColor = this.getDayCalendarColor(date);
    if (!calendarColor || !ApartmentSeasonType[calendarColor.apartmentSeasonType]) {
      return;
    }
    return ApartmentSeasonType[calendarColor.apartmentSeasonType];
  }

  cssCalendarType(date: NgbDate): string {
    const calendarColor = this.getDayCalendarColor(date);
    if (!calendarColor || !CalendarType[calendarColor.calendarType]) {
      return;
    }
    const cssClass = `${CalendarType[calendarColor.calendarType]}${CalendarDay[calendarColor.calendarDay]}`;
    const isoDateString = this.formatDate(date);

    if (!this.dayCssClasses[isoDateString]) {
      this.dayCssClasses[isoDateString] = '';
    }
    if (
      !this.dayCssClasses[isoDateString] ||
      (this.dayCssClasses[isoDateString] && !this.dayCssClasses[isoDateString].includes(cssClass))
    ) {
      this.dayCssClasses[isoDateString] += cssClass;
    }
    return this.dayCssClasses[isoDateString];
  }

  dayDescription(date: NgbDate): string {
    const calendarColor = this.getDayCalendarColor(date);
    if (!calendarColor) {
      return '';
    }

    let description = 'Available ';

    let price = calendarColor.apartmentSeasonPrice;

    if (
      CalendarType[calendarColor.calendarType] &&
      [CalendarType.reserved, CalendarType.reservedOwner].includes(calendarColor.calendarType) &&
      [CalendarDay.First, CalendarDay.Center].includes(calendarColor.calendarDay)
    ) {
      return `\n ${CalendarTypeLabel.get(calendarColor.calendarType)}`;
    }

    if (calendarColor.calendarDiscountPercentage) {
      price = price - (price * calendarColor.calendarDiscountPercentage) / 100;
    }

    if (ApartmentSeasonType[calendarColor.apartmentSeasonType]) {
      description +=
        `${ApartmentSeasonTypeLabel.get(calendarColor.apartmentSeasonType)} ` +
        `${this.currencyPipe.transform(price, 'EUR')}`;
    }

    if (
      CalendarType[calendarColor.calendarType] &&
      [CalendarDay.First, CalendarDay.Center].includes(calendarColor.calendarDay)
    ) {
      description += `\n ${CalendarTypeLabel.get(calendarColor.calendarType)}`;
      if (calendarColor.calendarDiscountPercentage) {
        description += ` ${calendarColor.calendarDiscountPercentage}%`;
      }
    }

    return description;
  }  

TEMPLATE:

<ngb-datepicker
  displayMonths="2"
  navigation="arrows"
  [dayTemplate]="dayTemplate"
  [showWeekNumbers]="true"
  outsideDays="hidden"
>
</ngb-datepicker>

<ng-template #dayTemplate let-date>
  <span class="custom-day" [ngClass]="cssCustomDay(date)" [ngbTooltip]="dayDescription(date)">
    <span>
      {{ date.day }}
    </span>
  </span>
</ng-template>
manzapanza
  • 6,087
  • 4
  • 39
  • 48

1 Answers1

0

To improve your code ( I don't know if the improve is a big improve):

getDayCalendarColor(date: NgbDate): CalendarColor {
    //use an auxiliar variable
    const dateSearch=this.formatDate(date);
    //use "find", not filter -return undefined if not found-
    return this.calendarColors.find(cC => cC.date ===dateSearch);
  }

You can also filter the calendarsColors when you change the month and year of the calendar

Another thing is not use a ngToolTip in each day or use context and manual tigger using (mouseover) and (mouseout) -I'm not sure about this last option-

Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • Thank you for you answer! I tried applying your suggestions, the code looks a little better but the improvements on performance are imperceptible. Also removing completely the ngbTooltip there's not differences.. after some minutes the page start freezing (also on stackblitz) – manzapanza Mar 19 '19 at 15:45