В настоящее время я работаю над календарем в своем приложении angular v8.
Я использую этот плагин: https://fullcalendar.io
это компонент, который я включаю в свой HTML-шаблон:
<full-calendar
defaultView = "dayGridMonth"
[editable] = "true"
[eventLimit] = "5"
[nowIndicator] = "true"
[slotLabelFormat] = "timeFormat"
[eventTimeFormat] = "timeFormat"
[eventClassName] = "'fc-event-brand'"
[minTime] = "'08:00:00'"
[maxTime] = "'24:00:00'"
[header] = "{
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth, timeGridWeek, timeGridDay, listWeek'
}"
[plugins] = "calendarPlugins"
[events] = "calendarEvents"
(eventMouseEnter) = "showPopover($event)"
(eventMouseLeave) = "hidePopover($event)"
(eventRender) = "renderTooltip($event)"></full-calendar>
Но как я могу добавить всплывающую подсказку или всплывающую подсказку ngBootstrap к элементу?
это renderTooltip():
renderTooltip(event) {
// bind ngBootstrap tooltip or popover to $event.el
}
🤔 А знаете ли вы, что...
JavaScript имеет множество библиотек и фреймворков, таких как jQuery, Angular, и Vue.js.
Я бы создал один простой компонент, который в основном представляет собой просто всплывающую оболочку:
@Component({
template: `
<div class = "fc-content" [ngbPopover] = "template" container = "body" triggers = "manual">
<ng-content></ng-content>
</div>
`,
})
export class PopoverWrapperComponent {
template: TemplateRef<any>;
@ViewChild(NgbPopover, { static: true }) popover: NgbPopover;
}
template
свойство будет передано из нашего основного компонента, поэтому мы можем создать любой шаблон, который захотим.NgbPopover
, чтобы мы могли использовать popover.open(context)
позже.Также убедитесь, что вы добавили этот компонент в массив entryComponents
вашего NgModule
:
@NgModule({
imports: [ BrowserModule, FullCalendarModule, NgbPopoverModule ],
declarations: [ AppComponent, PopoverWrapperComponent ],
entryComponents: [PopoverWrapperComponent],
/
like this
bootstrap: [ AppComponent ]
})
export class AppModule { }
Теперь мы собираемся динамически визуализировать этот компонент в элемент $event.el
и проецировать дочерние узлы в ng-content
.
import { Component, ComponentRef,
TemplateRef, ViewChild, ComponentFactoryResolver,
Injector, ApplicationRef } from '@angular/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import { NgbPopover } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
calendarPlugins = [dayGridPlugin];
calendarEvents = [
{ title: 'event 1', date: '2019-08-09', customProp1: 'customProp1', customProp2: 'customProp2' },
{ title: 'event 2', date: '2019-08-12', customProp1: 'customProp3', customProp2: 'customProp4' }
];
@ViewChild('popoverTmpl', { static: true }) popoverTmpl: TemplateRef<any>;
popoversMap = new Map<any, ComponentRef<PopoverWrapperComponent>>();
popoverFactory = this.resolver.resolveComponentFactory(PopoverWrapperComponent);
constructor(
private resolver: ComponentFactoryResolver,
private injector: Injector,
private appRef: ApplicationRef) {
}
renderTooltip(event) {
const projectableNodes = Array.from(event.el.childNodes)
const compRef = this.popoverFactory.create(this.injector, [projectableNodes], event.el);
compRef.instance.template = this.popoverTmpl;
this.appRef.attachView(compRef.hostView);
this.popoversMap.set(event.el, compRef);
}
destroyTooltip(event) {
const popover = this.popoversMap.get(event.el);
if (popover) {
this.appRef.detachView(popover.hostView);
popover.destroy();
this.popoversMap.delete(event.el);
}
}
showPopover(event) {
const popover = this.popoversMap.get(event.el);
if (popover) {
popover.instance.popover.open({ event: event.event });
}
}
hidePopover(event) {
const popover = this.popoversMap.get(event.el);
if (popover) {
popover.instance.popover.close();
}
}
}
Ключевой частью здесь является то, как мы визуализируем компонент динамически с проецируемыми узлами:
renderTooltip(event) {
const projectableNodes = Array.from(event.el.childNodes)
const compRef = this.popoverFactory.create(this.injector, [projectableNodes], event.el);
compRef.instance.template = this.popoverTmpl;
this.appRef.attachView(compRef.hostView)
this.popoversMap.set(event.el, compRef)
}
Динамически визуализируемый компонент не имеет отношения к дереву обнаружения изменений Angular, поэтому мы должны добавить его представление в ApplicationRef
представления, чтобы обнаружение изменений работало там.
Убедитесь, что вы подписались на следующее событие в своем шаблоне:
(eventRender) = "renderTooltip($event)"
(eventDestroy) = "destroyTooltip($event)"
(eventMouseEnter) = "showPopover($event)"
(eventMouseLeave) = "hidePopover($event)"
Вы также должны определить шаблон для всплывающего окна, т.е.:
<ng-template #popoverTmpl let-event = "event">
<h6>{{ event.title }}</h6>
<div>
<p>{{ event.extendedProps.customProp1 }}</p>
<p>{{ event.extendedProps.customProp2 }}</p>
</div>
</ng-template>
Пример Stackblitz с @fullcalendar/angular/5.5.0