1

So I am using angular-calendar and I have a dialog for when I press a button, right now I add a random event object to my calendarservice events array for testing purposes:

 onButtonClick() {
      var date = addHours(new Date(), 2)
      this.calendarService.onCreateEvent('test added',date )
      console.log(date)
    }

which adds it to my injected service:

export class CalendarService {
  events: CalendarEvent[] = [
    { title: "my test event 1", start: new Date() },
    { title: "my test event 2", start: addDays(new Date(), 1) }
  ];

Right now I use ngOnit to set the local events array in the component:

export class ScheduleCalendarComponent implements OnInit{
  constructor(
    private calendarService: CalendarService,
    public dialog: MatDialog
  ) {}

  view: string = "month";

  viewDate: Date = new Date();

  events: CalendarEvent[] = [];

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

  ngOnInit(): void {
    this.events = this.calendarService.events;
  }

So right now it pulls the correct events but when I add an event it doesnt update the DOM because I only update the array OnInit so only after changing pages and coming back, Using the calendarservice events array it works if I change the update method:

  onCreateEvent(title: string, start: any) {
    this.events = [...this.events, {title: title, start: start}]
  }

I use this and add it to the calendar like so:

 <mwl-calendar-day-view
    *ngSwitchCase="'day'"
    [viewDate]="viewDate"
    [events]="this.calendarService.events"
    (hourSegmentClicked)="openDialog()"
  >
  </mwl-calendar-day-view>

but how would I do this using the components own array rather than the service array? And is it better practice for the component to use its own array like max did than just take straight from the service?

I'd like to do it using the components array but It wont update on button click:

 <mwl-calendar-day-view
    *ngSwitchCase="'day'"
    [viewDate]="viewDate"
    [events]="events"
    (hourSegmentClicked)="openDialog()"
  >
  </mwl-calendar-day-view>

Hope that makes sense

Thanks you!

2 Answers2

0

Its happening because there are different changeDetectionStrategy and the one which you are seeing is changeDetectionStrategy.onPush under @Component

changeDetection: ChangeDetectionStrategy.OnPush

Why don't you create a new array copy using

ngOnInit(): void {
  this.events = [...this.calendarService.events];
}

OR

ngOnInit(): void {
  this.events = JSON.parse(JSON.stringify(this.calendarService.events));
}

and then you wont modify service array events and can easily use:

onCreateEvent(title: string, start: any) {
 this.events = [...this.events, {title: title, start: start}]
}
Shashank Vivek
  • 16,888
  • 8
  • 62
  • 104
  • Unfortunately, neither of these worked, I also tried changing the change detection strategy for each scenario, and none of them worked. the first solution you offered passed the events for service to component but the second one didn't even load the events that are hard coded in the service. – Syrus Yeung Mar 08 '19 at 18:58
  • maybe this has something to do with it being in ngOnit? I think I've seen it work thos way, however, but since it's only on the initialization of the page maybe it doesn't see it since its only oninit? but i figured since I was passing a reference object it would see it as being a whole new array whenever the service array is changed. not entirely sure – Syrus Yeung Mar 08 '19 at 19:07
  • @SyrusYeung did u find any solution – Shashank Vivek Mar 12 '19 at 04:59
0

I know this is an old question, but here is my solution that might help some people:

  1. You start by using a subscription to a subject, observable, whatever suits

  2. you make sure to force your calendar to refresh its view by using something like:

    export class MyComponentWithCalendarComponent implements OnInit, AfterViewInit, OnDestroy {
      @ViewChild(MatCalendar) calendar: MatCalendar<Date>;
      private subscription = new Subscription();
      data: Stuff[]
      ...
      ngAfterViewInit() {
        this.subscription.add(
    
        // remember this can be something else, like this.service.getStuff().subscribe({...
        this.stuffSubject.subscribe({
    
          next: (data: Stuff[]) => {
            this.data = data;
    
            // if your changes concern same month
            this.calendar.updateTodaysDate()
    
            // if your changes concern other months. this is what fixed the issue in my case =>
            const activeDate = new Date()
            this.calendar.activeDate = activeDate
    
          }
    }
    

I created an issue concerning this => line where "startAt" is missing for change detection as i believe @Input fields should be included when we expect changes. "activeDate" is just a workaround, at least to my best knowledge.

millenion
  • 1,218
  • 12
  • 16