5
votes

Here i am trying to build an app that use this angular calendar: https://mattlewis92.github.io/angular-calendar/#/kitchen-sink Is very popular i guess you know it. I am using Angular 6 with AngularFire2 and Firebase.

Here is my app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AngularFireModule } from 'angularfire2';
import { environment } from '../environments/environment';
import { NgModel, FormsModule } from '@angular/forms';
import { DragAndDropModule } from 'angular-draggable-droppable';
import { ResizeEvent } from 'angular-resizable-element';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
// tslint:disable-next-line:max-line-length
import {MatButtonModule, MatCheckboxModule, MatToolbarModule, MatSidenavModule, MatIconModule, MatListModule, MatGridListModule, MatCardModule, MatMenuModule, MatTableModule, MatPaginatorModule, MatSortModule} from '@angular/material';
import {LayoutModule} from '@angular/cdk/layout';
import { SidenavComponent } from './sidenav/sidenav.component';
import { RouterModule, Routes } from '@angular/router';
import { DashboardComponent } from './dashboard/dashboard.component';
import { TableComponent } from './table/table.component';
import { AngularFirestoreModule } from 'angularfire2/firestore';
import { AngularFireStorageModule } from 'angularfire2/storage';
import { AngularFireAuthModule } from 'angularfire2/auth';
import { CoreModule } from './core/core.module';
import { UserProfileComponent } from './user-profile/user-profile.component';
import { CalendarComponent } from './calendar/calendar.component';
import { ResizableModule } from 'angular-resizable-element';

@NgModule({
  declarations: [
    AppComponent,
    SidenavComponent,
    DashboardComponent,
    TableComponent,
    UserProfileComponent,
    CalendarComponent,
  ],
  imports: [
    ResizableModule,
    [DragAndDropModule.forRoot()],
    BrowserModule,
    AppRoutingModule,
    CoreModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFirestoreModule, // imports firebase/firestore, only needed for database features
    AngularFireAuthModule, // imports firebase/auth, only needed for auth features,
    AngularFireStorageModule, // imports firebase/storage only needed for storage features
    AppRoutingModule,
    [MatButtonModule, MatCheckboxModule],
    [BrowserAnimationsModule],
    LayoutModule,
    BrowserAnimationsModule,
    MatToolbarModule,
    MatButtonModule,
    MatSidenavModule,
    MatIconModule,
    MatListModule,
    MatGridListModule,
    MatCardModule,
    MatMenuModule,
    MatTableModule,
    MatPaginatorModule,
    MatSortModule,
  ],
  exports: [ RouterModule ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Ok here is my calendar.component.ts

import {
  Component,
  ChangeDetectionStrategy,
  ViewChild,
  TemplateRef
} from '@angular/core';
import {
  startOfDay,
  endOfDay,
  subDays,
  addDays,
  endOfMonth,
  isSameDay,
  isSameMonth,
  addHours
} from 'date-fns';
import { Subject } from 'rxjs';
import {
  CalendarEvent,
  CalendarEventAction,
  CalendarEventTimesChangedEvent
} from 'angular-calendar';
import { NgbModal } from '../../../node_modules/@ng-bootstrap/ng-bootstrap';

const colors: any = {
  red: {
    primary: '#ad2121',
    secondary: '#FAE3E3'
  },
  blue: {
    primary: '#1e90ff',
    secondary: '#D1E8FF'
  },
  yellow: {
    primary: '#e3bc08',
    secondary: '#FDF1BA'
  }
};

@Component({
  selector: 'app-calendar',
  changeDetection: ChangeDetectionStrategy.OnPush,
  styleUrls: ['calendar.component.css'],
  templateUrl: 'calendar.component.html'
})
export class CalendarComponent {
  @ViewChild('modalContent') modalContent: TemplateRef<any>;

  view = 'month';

  viewDate: Date = new Date();

  modalData: {
    action: string;
    event: CalendarEvent;
  };

  actions: CalendarEventAction[] = [
    {
      label: '<i class="fa fa-fw fa-pencil"></i>',
      onClick: ({ event }: { event: CalendarEvent }): void => {
        this.handleEvent('Edited', event);
      }
    },
    {
      label: '<i class="fa fa-fw fa-times"></i>',
      onClick: ({ event }: { event: CalendarEvent }): void => {
        this.events = this.events.filter(iEvent => iEvent !== event);
        this.handleEvent('Deleted', event);
      }
    }
  ];

  refresh: Subject<any> = new Subject();

  events: CalendarEvent[] = [
    {
      start: subDays(startOfDay(new Date()), 1),
      end: addDays(new Date(), 1),
      title: 'A 3 day event',
      color: colors.red,
      actions: this.actions
    },
    {
      start: startOfDay(new Date()),
      title: 'An event with no end date',
      color: colors.yellow,
      actions: this.actions
    },
    {
      start: subDays(endOfMonth(new Date()), 3),
      end: addDays(endOfMonth(new Date()), 3),
      title: 'A long event that spans 2 months',
      color: colors.blue
    },
    {
      start: addHours(startOfDay(new Date()), 2),
      end: new Date(),
      title: 'A draggable and resizable event',
      color: colors.yellow,
      actions: this.actions,
      resizable: {
        beforeStart: true,
        afterEnd: true
      },
      draggable: true
    }
  ];

  activeDayIsOpen = true;

  constructor(private modal: NgbModal) {}

  dayClicked({ date, events }: { date: Date; events: CalendarEvent[] }): void {
    if (isSameMonth(date, this.viewDate)) {
      this.viewDate = date;
      if (
        (isSameDay(this.viewDate, date) && this.activeDayIsOpen === true) ||
        events.length === 0
      ) {
        this.activeDayIsOpen = false;
      } else {
        this.activeDayIsOpen = true;
      }
    }
  }

  eventTimesChanged({
    event,
    newStart,
    newEnd
  }: CalendarEventTimesChangedEvent): void {
    event.start = newStart;
    event.end = newEnd;
    this.handleEvent('Dropped or resized', event);
    this.refresh.next();
  }

  handleEvent(action: string, event: CalendarEvent): void {
    this.modalData = { event, action };
    this.modal.open(this.modalContent, { size: 'lg' });
  }

  addEvent(): void {
    this.events.push({
      title: 'New event',
      start: startOfDay(new Date()),
      end: endOfDay(new Date()),
      color: colors.red,
      draggable: true,
      resizable: {
        beforeStart: true,
        afterEnd: true
      }
    });
    this.refresh.next();
  }
}

calendar.component.html

    <ng-template #modalContent let-close="close">
  <div class="modal-header">
    <h5 class="modal-title">Event action occurred</h5>
    <button type="button" class="close" (click)="close()">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
  <div class="modal-body">
    <div>
      Action:
      <pre>{{ modalData?.action }}</pre>
    </div>
    <div>
      Event:
      <pre>{{ modalData?.event | json }}</pre>
    </div>
  </div>
  <div class="modal-footer">
    <button type="button" class="btn btn-outline-secondary" (click)="close()">OK</button>
  </div>
</ng-template>

<div class="row text-center">
  <div class="col-md-4">
    <div class="btn-group">
      <div
        class="btn btn-primary"
        mwlCalendarPreviousView
        [view]="view"
        [(viewDate)]="viewDate"
        (viewDateChange)="activeDayIsOpen = false">
        Previous
      </div>
      <div
        class="btn btn-outline-secondary"
        mwlCalendarToday
        [(viewDate)]="viewDate">
        Today
      </div>
      <div
        class="btn btn-primary"
        mwlCalendarNextView
        [view]="view"
        [(viewDate)]="viewDate"
        (viewDateChange)="activeDayIsOpen = false">
        Next
      </div>
    </div>
  </div>
  <div class="col-md-4">
    <h3>{{ viewDate | calendarDate:(view + 'ViewTitle'):'en' }}</h3>
  </div>
  <div class="col-md-4">
    <div class="btn-group">
      <div
        class="btn btn-primary"
        (click)="view = 'month'"
        [class.active]="view === 'month'">
        Month
      </div>
      <div
        class="btn btn-primary"
        (click)="view = 'week'"
        [class.active]="view === 'week'">
        Week
      </div>
      <div
        class="btn btn-primary"
        (click)="view = 'day'"
        [class.active]="view === 'day'">
        Day
      </div>
    </div>
  </div>
</div>
<br>
<div [ngSwitch]="view">
  <mwl-calendar-month-view
    *ngSwitchCase="'month'"
    [viewDate]="viewDate"
    [events]="events"
    [refresh]="refresh"
    [activeDayIsOpen]="activeDayIsOpen"
    (dayClicked)="dayClicked($event.day)"
    (eventClicked)="handleEvent('Clicked', $event.event)"
    (eventTimesChanged)="eventTimesChanged($event)">
  </mwl-calendar-month-view>
  <mwl-calendar-week-view
    *ngSwitchCase="'week'"
    [viewDate]="viewDate"
    [events]="events"
    [refresh]="refresh"
    (eventClicked)="handleEvent('Clicked', $event.event)"
    (eventTimesChanged)="eventTimesChanged($event)">
  </mwl-calendar-week-view>
  <mwl-calendar-day-view
    *ngSwitchCase="'day'"
    [viewDate]="viewDate"
    [events]="events"
    [refresh]="refresh"
    (eventClicked)="handleEvent('Clicked', $event.event)"
    (eventTimesChanged)="eventTimesChanged($event)">
  </mwl-calendar-day-view>
</div>

<br><br><br>

<h3>
  Edit events
  <button
    class="btn btn-primary pull-right"
    (click)="addEvent()">
    Add new
  </button>
  <div class="clearfix"></div>
</h3>

<table class="table table-bordered">

  <thead>
    <tr>
      <th>Title</th>
      <th>Primary color</th>
      <th>Secondary color</th>
      <th>Starts at</th>
      <th>Ends at</th>
      <th>Remove</th>
    </tr>
  </thead>

  <tbody>
    <tr *ngFor="let event of events; let index = index">
      <td>
        <input
          type="text"
          class="form-control"
          [(ngModel)]="event.title"
          (keyup)="refresh.next()">
      </td>
      <td>
        <input
          type="color"
          [(ngModel)]="event.color.primary"
          (change)="refresh.next()">
      </td>
      <td>
        <input
          type="color"
          [(ngModel)]="event.color.secondary"
          (change)="refresh.next()">
      </td>
      <td>
        <input
          class="form-control"
          type="text"
          mwlFlatpickr
          [(ngModel)]="event.start"
          (ngModelChange)="refresh.next()"
          [altInput]="true"
          [convertModelValue]="true"
          [enableTime]="true"
          dateFormat="Y-m-dTH:i"
          altFormat="F j, Y H:i"
          placeholder="Not set">
      </td>
      <td>
        <input
          class="form-control"
          type="text"
          mwlFlatpickr
          [(ngModel)]="event.end"
          (ngModelChange)="refresh.next()"
          [altInput]="true"
          [convertModelValue]="true"
          [enableTime]="true"
          dateFormat="Y-m-dTH:i"
          altFormat="F j, Y H:i"
          placeholder="Not set">
      </td>
      <td>
        <button
          class="btn btn-danger"
          (click)="events.splice(index, 1); refresh.next()">
          Delete
        </button>
      </td>
    </tr>
  </tbody>

</table>

I am junior with Angular and i may miss something little. Please if you can help me solve this i would really appreciate it. Here is the error i get

Uncaught Error: Template parse errors: Can't bind to 'view' since it isn't a known property of 'div'. (" class="btn btn-primary" mwlCalendarPreviousView [ERROR ->][view]="view" [(viewDate)]="viewDate" (viewDateChange)="activeDayIsOpen = false"> "): ng:///AppModule/CalendarComponent.html@28:8 Can't bind to 'viewDate' since it isn't a known property of 'div'. (" mwlCalendarPreviousView [view]="view" [ERROR ->][(viewDate)]="viewDate" (viewDateChange)="activeDayIsOpen = false"> Previous "): ng:///AppModule/CalendarComponent.html@29:8 Can't bind to 'viewDate' since it isn't a known property of 'div'. (" class="btn btn-outline-secondary" mwlCalendarToday [ERROR ->][(viewDate)]="viewDate"> Today "): ng:///AppModule/CalendarComponent.html@36:8 Can't bind to 'view' since it isn't a known property of 'div'. (" class="btn btn-primary" mwlCalendarNextView [ERROR ->][view]="view" [(viewDate)]="viewDate" (viewDateChange)="activeDayIsOpen = false"> "): ng:///AppModule/CalendarComponent.html@42:8 Can't bind to 'viewDate' since it isn't a known property of 'div'. (" mwlCalendarNextView [view]="view" [ERROR ->][(viewDate)]="viewDate" (viewDateChange)="activeDayIsOpen = false"> Next "): ng:///AppModule/CalendarComponent.html@43:8 The pipe 'calendarDate' could not be found ("

{{ [ERROR ->]viewDate | calendarDate:(view + 'ViewTitle'):'en' }}

"): ng:///AppModule/CalendarComponent.html@50:11 Can't bind to 'viewDate' since it isn't a known property of 'mwl-calendar-month-view'. 1. If 'mwl-calendar-month-view' is an Angular component and it has 'viewDate' input, then verify that it is part of this module. 2. If 'mwl-calendar-month-view' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. 3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. (" ][viewDate]="viewDate" [events]="events" [refresh]="refresh" "): ng:///AppModule/CalendarComponent.html@79:4 Can't bind to 'events' since it isn't a known property of 'mwl-calendar-month-view'. 1. If 'mwl-calendar-month-view' is an Angular component and it has 'events' input, then verify that it is part of this module. 2. If 'mwl-calendar-month-view' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. 3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. (" *ngSwitchCase="'month'" [viewDate]="viewDate" [ERROR ->][events]="events" [refresh]="refresh" [activeDayIsOpen]="activeDayIsOpen" "): ng:///AppModule/CalendarComponent.html@80:4 Can't bind to 'refresh' since it isn't a known property of 'mwl-calendar-month-view'. 1. If 'mwl-calendar-month-view' is an Angular component and it has 'refresh' input, then verify that it is part of this module. 2. If 'mwl-calendar-month-view' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. 3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. (" [viewDate]="viewDate" [events]="events" [ERROR ->][refresh]="refresh" [activeDayIsOpen]="activeDayIsOpen" (dayClicked)="dayClicked($event.day)""): ng:///AppModule/CalendarComponent.html@81:4 Can't bind to 'activeDayIsOpen' since it isn't a known property of 'mwl-calendar-month-view'. 1. If 'mwl-calendar-month-view' is an Angular component and it has 'activeDayIsOpen' input, then verify that it is part of this module. 2. If 'mwl-calendar-month-view' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. 3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. (" [events]="events" [refresh]="refresh" [ERROR ->][activeDayIsOpen]="activeDayIsOpen" (dayClicked)="dayClicked($event.day)" (eventClicked)="han"): ng:///AppModule/CalendarComponent.html@82:4 'mwl-calendar-month-view' is not a known element: 1. If 'mwl-calendar-month-view' is an Angular component, then verify that it is part of this module. 2. If 'mwl-calendar-month-view' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. ("
[ERROR ->]) at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._compileComponents (compiler.js:23930) at compiler.js:23840 at Object.then (compiler.js:1007) at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._compileModuleAndComponents (compiler.js:23839)
2
Based on the error messages, it looks like there are issues coming from CalendarComponent.html. Can you please edit your question to include the code in calendar.component.html?Vlad274
I edited the question and added the calendar.component.html is there now.Florescu Catalin

2 Answers

2
votes

It looks like whatever library you're using for the mwlCalendarPreviousView and mwlCalendarNextViewdirectives and mwl-calendar-month-view component is not present/imported correctly.


The example link you provided has a link to this StackBlitz. Looking at module.ts, there are several module imports present that are missing from your app.module.ts. Since you're having issues with the calendar, I think you need to add this import

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    NgbModalModule.forRoot(),
    FlatpickrModule.forRoot(),
    CalendarModule.forRoot() <---- This One
  ],
  declarations: [DemoComponent],
  exports: [DemoComponent]
})
export class DemoModule {}
-1
votes

First, install through npm:

npm install --save angular-calendar date-fns

Next include the CSS file in the global (not component scoped) styles of your app:

/* angular-cli file: src/styles.css */
@import "../node_modules/angular-calendar/css/angular-calendar.css";

Finally import the calendar module into your apps module:

import { NgModule } from '@angular/core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { CalendarModule, DateAdapter } from 'angular-calendar';
import { adapterFactory } from 'angular-calendar/date-adapters/date-fns';

@NgModule({
  imports: [
    BrowserAnimationsModule,
    CalendarModule.forRoot({
      provide: DateAdapter,
      useFactory: adapterFactory
    })
  ]
})
export class MyModule {}

Then from the source code take related all the files.

This should resolve your issue. Happy coding!