Search code examples
angularangular17angular-calendar

How can I use angular-calendar in Angular 17 as a standalone project?


I'm trying to add the angular-calendar to my standalone project, but the demos only work if you have app.module.ts, which I don't have as I'm using a standalone project. This is the one I'm trying to implement: https://mattlewis92.github.io/angular-calendar/#/clickable-days

Any kind of help is appreciated!

This is what I've tried: component.ts:

import { bootstrapApplication } from '@angular/platform-browser';
import { Component, importProvidersFrom } from '@angular/core';
import { provideAnimations } from '@angular/platform-browser/animations';
import 'zone.js';
import { Subject } from 'rxjs';
import {
  CalendarModule,
  CalendarEvent,
  CalendarEventTimesChangedEvent,
  CalendarDayViewBeforeRenderEvent,
  CalendarWeekViewBeforeRenderEvent,
  DateAdapter,
  CalendarUtils,
} from 'angular-calendar';
import { CommonModule } from '@angular/common';
import { adapterFactory } from 'angular-calendar/date-adapters/date-fns';
import { HttpClientModule } from '@angular/common/http';

import {ChangeDetectionStrategy } from '@angular/core';
import {CalendarView } from 'angular-calendar';

@Component({
  selector: 'mwl-demo-component',
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
  templateUrl: './simple-calendar.component.html',
})
export class SimpleCalendarComponent {
  view: CalendarView = CalendarView.Month;

  viewDate: Date = new Date();

  events: CalendarEvent[] = [];

  clickedDate: Date;

  clickedColumn: number;
}

bootstrapApplication(SimpleCalendarComponent, {
  providers: [
    provideAnimations(),
    importProvidersFrom(
      CalendarModule.forRoot({
        provide: DateAdapter,
        useFactory: adapterFactory,
      })
    ),
    CalendarUtils
  ],
});

this is the component.html:

<mwl-demo-utils-calendar-header [(view)]="view" [(viewDate)]="viewDate">
</mwl-demo-utils-calendar-header>

<div class="alert alert-info">
  Click on a day or time slot on the view.
  <strong *ngIf="clickedDate"
    >You clicked on this time: {{ clickedDate | date:'medium' }}</strong
  >
  <strong *ngIf="clickedColumn !== undefined"
    >You clicked on this column: {{ clickedColumn }}</strong
  >
</div>

<div [ngSwitch]="view">
  <mwl-calendar-month-view
    *ngSwitchCase="'month'"
    [viewDate]="viewDate"
    [events]="events"
    (columnHeaderClicked)="clickedColumn = $event.isoDayNumber"
    (dayClicked)="clickedDate = $event.day.date"
  >
  </mwl-calendar-month-view>
  <mwl-calendar-week-view
    *ngSwitchCase="'week'"
    [viewDate]="viewDate"
    [events]="events"
    (dayHeaderClicked)="clickedDate = $event.day.date"
    (hourSegmentClicked)="clickedDate = $event.date"
  >
  </mwl-calendar-week-view>
  <mwl-calendar-day-view
    *ngSwitchCase="'day'"
    [viewDate]="viewDate"
    [events]="events"
    (hourSegmentClicked)="clickedDate = $event.date"
  >
  </mwl-calendar-day-view>
</div>

And this is the error I'm getting:

NG8001: 'mwl-demo-utils-calendar-header' is not a known element:
1. If 'mwl-demo-utils-calendar-header' is an Angular component, then verify that it is included in the '@Component.imports' of this component.
2. If 'mwl-demo-utils-calendar-header' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@Component.schemas' of this component to suppress this message.

It doesn't recognize angular-calendar elements, because I obviously made something wrong.


Solution

  • bootstrapApplication is angular's entry point, you shouldn't call this function in any component. You can provide the Canlendar module in app.config.ts(Angular 17+ bootstrap standalone component by default).

    import {ApplicationConfig, importProvidersFrom, provideZoneChangeDetection} from '@angular/core';
    import { provideRouter } from '@angular/router';
    
    import { routes } from './app.routes';
    import { provideClientHydration } from '@angular/platform-browser';
    import {CalendarModule, DateAdapter} from "angular-calendar";
    import {adapterFactory} from "angular-calendar/date-adapters/date-fns";
    
    export const appConfig: ApplicationConfig = {
      providers: [
        provideZoneChangeDetection({ eventCoalescing: true }),
        provideRouter(routes),
        provideClientHydration(),
        importProvidersFrom(
          CalendarModule.forRoot({
            provide: DateAdapter,
            useFactory: adapterFactory,
          })
        )
      ]
    };