如何以编程方式将ngBootstrap popover添加到element? [英] how to programmatically add ngBootstrap popover to element?

查看:101
本文介绍了如何以编程方式将ngBootstrap popover添加到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 use popover.open(context) later.
    • 还要确保已将此组件添加到NgModuleentryComponents数组中:

      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示例

      Stackblitz Example

      这篇关于如何以编程方式将ngBootstrap popover添加到element?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆