如何以编程方式将ngBootstrap popover添加到element? [英] how to programmatically add ngBootstrap popover to element?
问题描述
我目前正在使用我的angular v8应用程序中的日历.
I am currently workingon a calendar in my angular v8 application.
这是我使用的插件: https://fullcalendar.io
这是我包含在html模板中的组件:
this is the component which I include in my html template:
<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弹出窗口?
But how can I add a ngBootstrap popover to an element?
这是renderTooltip():
this is the renderTooltip():
renderTooltip(event) {
// bind ngBootstrap tooltip or popover to $event.el
}
希望有人可以帮助我为日历上的事件提供弹出窗口或工具提示.
Hope someone can help me out render the popover or tooltip to the events on the calendar.
推荐答案
我将创建一个简单的组件,该组件基本上只是一个popover包装器:
I would create one simple component which is basically just a popover wrapper:
@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)
. template
property will be passed from our main component so we can create any template we want- we also hold of
NgbPopover
instance so we can usepopover.open(context)
later.
还要确保已将此组件添加到NgModule
的entryComponents
数组中:
Also make sure you've added this component to entryComponents
array of your NgModule
:
@NgModule({
imports: [ BrowserModule, FullCalendarModule, NgbPopoverModule ],
declarations: [ AppComponent, PopoverWrapperComponent ],
entryComponents: [PopoverWrapperComponent],
\/
like this
bootstrap: [ AppComponent ]
})
export class AppModule { }
现在,我们要将该组件动态渲染到$event.el
元素中,并在ng-content
中投影子节点.
Now we're going to dynamically render this component into $event.el
element and project child nodes in 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();
}
}
}
这里的关键部分是我们如何使用可投影节点动态渲染组件动态 :
The key part here is how we're rendering component dynamically with projectable nodes:
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
视图中,以便更改检测应该在那里进行.
Rendered dynamically component has no relation to the Angular change detection tree so we have to add its view to ApplicationRef
views so change detection should work there.
确保已在模板中预订了以下事件:
Make sure you've subscribed to the following event in your template:
(eventRender)="renderTooltip($event)"
(eventDestroy)="destroyTooltip($event)"
(eventMouseEnter)="showPopover($event)"
(eventMouseLeave)="hidePopover($event)"
您还应该定义弹出框模板,即:
You should also define template for popover, i.e.:
<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 Example
这篇关于如何以编程方式将ngBootstrap popover添加到element?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!