将Angular组件注入FullCalendar事件条目

时间:2019-02-21 09:09:00

标签: angular fullcalendar primeng

PrimeNG 7 introduced一个<p-fullCalendar>组件,将FullCalendar 4.0库包装为Angular组件。例如

<p-fullCalendar [options]="options" [events]="events"></p-fullCalendar>

FullCalendar选项包括eventRender选项,用于指定用于自定义日历中事件呈现方式的函数。我在下面的示例中使用了它,但是它使用标准Javascript生成了DOM Elements,因此不能包含任何其他Angular组件,例如示例中的Material设计样式的按钮(它仍然会创建一个基本的未样式化按钮(因为使用了标准<button>)。

我尝试研究诸如使用Angular的[innerHTML]ViewContainerRef with ComponentFactoryResolver或Angular的runtime JIT compiler之类的选项,但是我对让这些方法中的任何一种工作还是知道哪种最适合此用例。如何将Angular组件注入FullCalendar事件条目中?

它不需要是完全动态的,例如具有隐藏的组件(已在页面上显示但显示在正确的位置),或者仅以不同的方式实例化ng-templates可能会很好,只要它在日历上显示并像在日历上一样正确输入即可。

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-calendar',
  templateUrl: './calendar.component.html',
  styleUrls: ['./calendar.component.scss']
})
export class CalendarComponent implements OnInit {

  options: any;
  events: any[];

  constructor() { }

  ngOnInit() {
    this.events = [
        {
            "title": "All Day Event",
            "start": "2019-02-01"
        },
        {
            "title": "Long Event",
            "start": "2019-02-07",
            "end": "2019-02-10"
        },
        {
            "title": "Repeating Event",
            "start": "2019-02-09T16:00:00"
        },
        {
            "title": "Repeating Event",
            "start": "2019-02-16T16:00:00",
            'color': 'rgb(72,101,144)',
            'textColor': 'black',
        },
        {
            "title": "Conference",
            "start": "2019-02-11",
            "end": "2019-02-13"
        },
        {
            "title": "John Smith",
            "start": "2019-02-01T10:00:00"
        },
        {
          "title": "Appointment",
          "start": "2019-02-01T16:00:00"
        },
    ];

    this.refreshOptions();
  }

  refreshOptions() {
    this.options = { eventRender: this.onRender };
  }

  onRender(info: any) {
    let title = info.event.title;
    let start = info.event.start;
    let end = info.event.end;
    if (!info.event.allDay) {
      return createElementFromHTML(
        '<a class="fc-day-grid-event fc-event">' +
        '  <div class="fc-content">' +
        '    <span>' + event.title + '</span>' +
        '    <button mat-raised-button>Button</button>'+
        '  </div>'+
        '</a>');
    }
  }

}

// Use Javascript to generate DOM Elements    
function createElementFromHTML(htmlString) {
  var div = document.createElement('div');
  div.innerHTML = htmlString.trim();

  // Change this to div.childNodes to support multiple top-level nodes
  return div.firstChild; 
}

1 个答案:

答案 0 :(得分:0)

这可能与我几个月前刚接触的内容有关。您可以查看我概述的here答案。

使用Angular的 DomPortalHost ,我能够轻松地将组件注入DOM中的任何地方

编辑:这是一个示例代码段

import { ComponentFactoryResolver, ApplicationRef } from '@angular/core';
import { ComponentPortal, DomPortalHost } from '@angular/cdk/portal';

import { TheComponentThatIWantToAppend } from '../path-to-component-that-i-want-to-append'; 

constructor(
    protected componentFactoryResolver: ComponentFactoryResolver,
    protected appRef: ApplicationRef,
    protected injector: Injector
) {}
...

myfunction (): void {
    let myElementContainer = new DomPortalHost(
      eventRenderInfo.el.querySelector('.my-element-container'), // Target the element where you wish to append your component
      this.componentFactoryResolver,
      this.appRef,
      this.injector);

      myElementContainer.attach(new ComponentPortal(TheComponentThatIWantToAppend)); // This does the trick
}