将 Angular 组件注入 FullCalendar 事件条目

Sil*_*eri 5 fullcalendar primeng angular

PrimeNG 7引入了一个<p-fullCalendar>FullCalendar 4.0库包装为 Angular 组件的组件。例如

<p-fullCalendar [options]="options" [events]="events"></p-fullCalendar>
Run Code Online (Sandbox Code Playgroud)

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

我曾尝试研究诸如使用 Angular 的[innerHTML], ViewContainerRefwithComponentFactoryResolver或 Angular 的运行时 JIT 编译器之类的选项,但我不太了解这些方法中的任何一种,或者不知道哪种方法最适合这个用例。如何将 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; 
}
Run Code Online (Sandbox Code Playgroud)

Dre*_*aut 0

这可能与我几个月前的经历有关。您可以查看我在这里列出的答案。

使用 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
}
Run Code Online (Sandbox Code Playgroud)