Skip to content

Commit

Permalink
fixes to template slots
Browse files Browse the repository at this point in the history
  • Loading branch information
arshaw committed Dec 1, 2022
1 parent 85986bf commit 7a0f4b7
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 47 deletions.
6 changes: 5 additions & 1 deletion app/src/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@
*ngIf="calendarOptions"
#fullcalendar
[options]="calendarOptions"
></full-calendar>
>
<ng-template #eventContent let-arg>
<b>{{ arg.event.title }}</b> - {{ arg.event.start.getDate() }}
</ng-template>
</full-calendar>
2 changes: 1 addition & 1 deletion app/src/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class AppComponent implements OnInit {
const yearMonth = nowDate.getUTCFullYear() + '-' + (nowDate.getUTCMonth() + 1);

this.calendarOptions!.events = [{
title: 'Updaten Event',
title: 'Updated Event',
start: yearMonth + '-08',
end: yearMonth + '-10'
}];
Expand Down
2 changes: 1 addition & 1 deletion lib/src/full-calendar.component.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<offscreen-fragment>
<transport-container *ngFor="let customRendering of customRenderingMap.values()"
<transport-container *ngFor="let customRendering of customRenderings"
[inPlaceOf]="customRendering.containerEl"
[elTag]="customRendering.elTag"
[elClasses]="customRendering.elClasses"
Expand Down
64 changes: 31 additions & 33 deletions lib/src/full-calendar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,20 @@ import {
AfterContentChecked,
OnDestroy,
ViewEncapsulation,
OnChanges,
} from '@angular/core';
import { Calendar, CalendarOptions } from '@fullcalendar/core';
import { CustomRendering, CustomRenderingStore } from '@fullcalendar/core/internal';
import { OPTION_INPUT_NAMES, OPTION_IS_DEEP, OPTION_TEMPLATE_NAMES } from './options';
import { OPTION_INPUT_NAMES, OPTION_TEMPLATE_NAMES, OPTION_IS_DEEP } from './options';
import { CalendarOption, CalendarTemplateRef } from './private-types';
import { deepEqual } from './utils/fast-deep-equal';
import { deepCopy, shallowCopy, mapHash } from './utils/obj';
import { deepEqual } from './utils/fast-deep-equal';

@Component({
selector: 'full-calendar',
templateUrl: './full-calendar.component.html',
encapsulation: ViewEncapsulation.None // the styles are root-level, not scoped within the component
})
export class FullCalendarComponent implements OnChanges, AfterViewInit, DoCheck, AfterContentChecked, OnDestroy {
export class FullCalendarComponent implements AfterViewInit, DoCheck, AfterContentChecked, OnDestroy {
@Input() options?: CalendarOptions;
@Input() deepChangeDetection?: boolean;

Expand All @@ -38,43 +37,32 @@ export class FullCalendarComponent implements OnChanges, AfterViewInit, DoCheck,
/*
NOTE: keep in sync with OPTION_TEMPLATE_NAMES
*/
@ContentChild('allDayContent') allDayContent?: CalendarTemplateRef<'allDayContent'>;
@ContentChild('noEventsContent') noEventsContent?: CalendarTemplateRef<'noEventsContent'>;
@ContentChild('eventContent') eventContent?: CalendarTemplateRef<'eventContent'>;
@ContentChild('allDayContent', { static: true }) allDayContent?: CalendarTemplateRef<'allDayContent'>;
@ContentChild('noEventsContent', { static: true }) noEventsContent?: CalendarTemplateRef<'noEventsContent'>;
@ContentChild('eventContent', { static: true }) eventContent?: CalendarTemplateRef<'eventContent'>;

private calendar: Calendar | null = null;
private optionSnapshot: Record<string, any> = {}; // for diffing
private handleCustomRendering: (customRendering: CustomRendering<any>) => void
public customRenderingMap = new Map<string, CustomRendering<any>>()
private customRenderingMap = new Map<string, CustomRendering<any>>()
private customRenderingArray?: CustomRendering<any>[]
public templateMap: { [templateName: string]: TemplateRef<any> } = {}

constructor(private element: ElementRef) {
const customRenderingStore = new CustomRenderingStore()
const customRenderingStore = new CustomRenderingStore();

customRenderingStore.subscribe((customRenderingMap) => {
this.customRenderingMap = customRenderingMap
})

this.handleCustomRendering = customRenderingStore.handle.bind(customRenderingStore)
}

ngOnChanges(): void {
const templateMap: { [templateName: string]: TemplateRef<any> } = {};

for (const templateName of OPTION_TEMPLATE_NAMES) {
const templateRef: TemplateRef<any> | undefined = (this as any)[templateName];

if (templateRef) {
templateMap[templateName] = templateRef
}
}
this.customRenderingArray = undefined // clear cache
});

this.templateMap = templateMap
this.handleCustomRendering = customRenderingStore.handle.bind(customRenderingStore);
this.templateMap = this as any; // alias to this
}

ngAfterViewInit() {
const { deepChangeDetection } = this;
const options = this.buildOptions();
const options = this.options || {};

// initialize snapshot
this.optionSnapshot = mapHash(options, (optionVal: any, optionName: string) => (
Expand All @@ -83,7 +71,10 @@ export class FullCalendarComponent implements OnChanges, AfterViewInit, DoCheck,
: optionVal
));

this.calendar = new Calendar(this.element.nativeElement, options);
this.calendar = new Calendar(this.element.nativeElement, {
...options,
...this.buildExtraOptions(),
});
this.calendar.render();
}

Expand All @@ -94,7 +85,7 @@ export class FullCalendarComponent implements OnChanges, AfterViewInit, DoCheck,
ngDoCheck() {
if (this.calendar) { // not the initial render
const { deepChangeDetection, optionSnapshot } = this;
const newOptions = this.buildOptions();
const newOptions = this.options || {};
const newProcessedOptions: Record<string, any> = {};
let anyChanges = false;

Expand Down Expand Up @@ -136,7 +127,10 @@ export class FullCalendarComponent implements OnChanges, AfterViewInit, DoCheck,

if (anyChanges) {
this.calendar.pauseRendering();
this.calendar.resetOptions(newProcessedOptions);
this.calendar.resetOptions({
...newProcessedOptions,
...this.buildExtraOptions(),
});
}
}
}
Expand All @@ -154,28 +148,32 @@ export class FullCalendarComponent implements OnChanges, AfterViewInit, DoCheck,
}
}

get customRenderings(): CustomRendering<any>[] {
return this.customRenderingArray ||
(this.customRenderingArray = [...this.customRenderingMap.values()]);
}

public getApi(): Calendar {
return this.calendar!;
}

private buildOptions(): CalendarOptions {
private buildExtraOptions(): CalendarOptions {
const customRenderingMetaMap: { [templateName: string]: boolean } = {};

for (const templateName of OPTION_TEMPLATE_NAMES) {
customRenderingMetaMap[templateName] = Boolean((this as any)[templateName]);
}

const options: CalendarOptions = {
...this.options,
customRenderingMetaMap,
handleCustomRendering: this.handleCustomRendering,
};

for (const inputName of OPTION_INPUT_NAMES) {
const inputValue = (this as any)[inputName]
const inputValue = (this as any)[inputName];

if (inputValue !== undefined) {
(options as any)[inputName] = inputValue
(options as any)[inputName] = inputValue;
}
}

Expand Down
12 changes: 6 additions & 6 deletions lib/src/utils/transport-container.component.html
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
<ng-template [ngIf]="elTag == 'div'">
<div #rootEl [ngClass]="elClasses || []" [ngStyle]="elStyle || {}">
<div #rootEl [ngClass]="elClasses || ''" [ngStyle]="elStyle || null">
<ng-container
[ngTemplateOutlet]="template"
[ngTemplateOutletContext]="{ $implicit: renderProps }"
></ng-container>
</div>
</ng-template>
<ng-template [ngIf]="elTag == 'span'">
<span #rootEl [ngClass]="elClasses || []" [ngStyle]="elStyle || {}">
<span #rootEl [ngClass]="elClasses || ''" [ngStyle]="elStyle || null">
<ng-container
[ngTemplateOutlet]="template"
[ngTemplateOutletContext]="{ $implicit: renderProps }"
></ng-container>
</span>
</ng-template>
<ng-template [ngIf]="elTag == 'a'">
<a #rootEl [ngClass]="elClasses || []" [ngStyle]="elStyle || {}">
<a #rootEl [ngClass]="elClasses || ''" [ngStyle]="elStyle || null">
<ng-container
[ngTemplateOutlet]="template"
[ngTemplateOutletContext]="{ $implicit: renderProps }"
></ng-container>
</a>
</ng-template>
<ng-template [ngIf]="elTag == 'tr'">
<tr #rootEl [ngClass]="elClasses || []" [ngStyle]="elStyle || {}">
<tr #rootEl [ngClass]="elClasses || ''" [ngStyle]="elStyle || null">
<ng-container
[ngTemplateOutlet]="template"
[ngTemplateOutletContext]="{ $implicit: renderProps }"
></ng-container>
</tr>
</ng-template>
<ng-template [ngIf]="elTag == 'th'">
<th #rootEl [ngClass]="elClasses || []" [ngStyle]="elStyle || {}">
<th #rootEl [ngClass]="elClasses || ''" [ngStyle]="elStyle || null">
<ng-container
[ngTemplateOutlet]="template"
[ngTemplateOutletContext]="{ $implicit: renderProps }"
></ng-container>
</th>
</ng-template>
<ng-template [ngIf]="elTag == 'td'">
<td #rootEl [ngClass]="elClasses || []" [ngStyle]="elStyle || {}">
<td #rootEl [ngClass]="elClasses || ''" [ngStyle]="elStyle || null">
<ng-container
[ngTemplateOutlet]="template"
[ngTemplateOutletContext]="{ $implicit: renderProps }"
Expand Down
12 changes: 7 additions & 5 deletions lib/src/utils/transport-container.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ export class TransportContainerComponent implements OnChanges, AfterViewInit, On
@Input() template!: TemplateRef<any>; // required
@Input() renderProps?: any;

@ViewChild('rootEl') rootElRef!: ElementRef;
@ViewChild('rootEl') rootElRef?: ElementRef;

ngAfterViewInit() {
const rootEl = this.rootElRef.nativeElement;
const rootEl: Element = this.rootElRef?.nativeElement; // assumed defined

replaceEl(rootEl, this.inPlaceOf);
applyElAttrs(rootEl, undefined, this.elAttrs);
}

ngOnChanges(changes: SimpleChanges) {
const rootEl = this.rootElRef.nativeElement;
const rootEl: Element | undefined = this.rootElRef?.nativeElement;

// ngOnChanges is called before ngAfterViewInit (and before DOM initializes)
// so make sure rootEl is defined before doing anything
Expand Down Expand Up @@ -72,13 +72,15 @@ function applyElAttrs(
previousAttrs: Record<string, any> = {},
currentAttrs: Record<string, any> = {}
): void {
// these are called "attributes" but they manipulate DOM node *properties*

for (const attrName in previousAttrs) {
if (!(attrName in currentAttrs)) {
el.removeAttribute(attrName);
(el as any)[attrName] = null;
}
}

for (const attrName in currentAttrs) {
el.setAttribute(attrName, currentAttrs[attrName]);
(el as any)[attrName] = currentAttrs[attrName];
}
}

0 comments on commit 7a0f4b7

Please sign in to comment.