簡體   English   中英

通過Wordpress REST API渲染Angular組件

[英]Render Angular component via Wordpress REST API

我有一個Angular 5應用程序,它通過REST API使用Wordpress中的內容。

我想做的是在Wordpress內容編輯器中插入一個組件標簽,然后將其顯示在應用程序中。

例如,我創建了一個簡單的組件<app-some-component></app-some-component>

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

@Component({
  selector: 'app-some-component',
  template: `
  <h1>I am a component!</h1>
  `
})
export class SomeComponent implements OnInit {
  constructor() {}

  ngOnInit() {}
}

並將其直接添加到主機組件模板進行測試,即可正常工作。

現在,此主機組件還通過其余API從Wordpress中提取內容。 因此,我嘗試在Wordpress內容編輯器中添加<app-some-component></app-some-component>

標簽“通過”到Angular應用程序,在檢查頁面時,我在HTML中看到該標簽。 但是組件的內容無法渲染,因此我想它不是由Angular處理的。

我正在使用安全管道來允許組件中的HTML,如下所示:

        <div class="card"
           *ngFor="let vid of videolist">
        <img class="card-img-top img-fluid"
             [src]="vid.better_featured_image.source_url"
             alt="Video Thumbnail">
        <div class="card-body">
          <h4 class="card-title"
              [innerHTML]="vid.title.rendered"></h4>
          <p class="card-text"
             [innerHTML]="vid.content.rendered | safe: 'html'"></p>
        </div>
        <div class="card-footer">
          <a routerLink="/videos/{{vid.id}}">View Video</a>
        </div>
      </div>

管道的代碼是

import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer, SafeHtml, SafeStyle, SafeScript, SafeUrl, SafeResourceUrl } from '@angular/platform-browser';

@Pipe({ name: 'safe' })

// see https://medium.com/@swarnakishore/angular-safe-pipe-implementation-to-bypass-domsanitizer-stripping-out-content-c1bf0f1cc36b
// usage: <div [innerHtml]="htmlSnippet | safe: 'html'"></div>
export class SafePipe implements PipeTransform {
  constructor(protected sanitizer: DomSanitizer) {}

  public transform(value: any, type: string): SafeHtml | SafeStyle | SafeScript | SafeUrl | SafeResourceUrl {
    switch (type) {
      case 'html':
        return this.sanitizer.bypassSecurityTrustHtml(value);
      case 'style':
        return this.sanitizer.bypassSecurityTrustStyle(value);
      case 'script':
        return this.sanitizer.bypassSecurityTrustScript(value);
      case 'url':
        return this.sanitizer.bypassSecurityTrustUrl(value);
      case 'resourceUrl':
        return this.sanitizer.bypassSecurityTrustResourceUrl(value);

      default:
        throw new Error(`Invalid safe type specified: ${type}`);
    }
  }
}

我需要怎么做才能渲染組件?

這只是將純HTML編寫到dom,您需要Angular才能將其實際呈現為組件。 為此,您有一些選擇:

您可以編寫帶有許多*ngIf*ngSwitch指令的組件:

import { Component, Input } from '@angular/core'

@Component({
  selector: 'app-blog-post',
  template: `
    <article>
      <ng-container *ngFor="let data of datas">
        <app-component-1 [data]="data" *ngIf="data.type === '1'"></app-component-1>
        <app-component-2 [data]="data" *ngIf="data.type === '2'"></app-component-2>
        <app-component-3 [data]="data" *ngIf="data.type === '3'"></app-component-3>
      </ng-container>
    </article>
  `,
  styleUrls: ['./blog-post.component.scss'],
})
export class BlogPostComponent {
  @Input() datas: any[]
}

您可以使用Angular Dynamic Component Loader來以編程方式渲染組件:

import {
  Component,
  ComponentFactoryResolver,
  Input,
  OnInit,
  ViewChild,
  ViewContainerRef,
} from '@angular/core'
import { Component1 } from '../component-1/component-1.component'
import { Component2 } from '../component-2/component-2.component'
import { Component3 } from '../component-3/component-3.component'

@Component({
  selector: 'app-blog-post',
  template: `
    <article>
      <app-blog-post-micro-component *ngFor="let data of datas" [data]="data"></app-blog-post-micro-component>
    </article>
  `,
})
export class BlogPostComponent {
  @Input() datas: any[]
}


@Component({
  selector: 'app-blog-post-micro-component',
  template: '<ng-container #container></ng-container>',
})
export class BlogPostMicroComponent implements OnInit {
  @Input() data: any[]
  @ViewChild('container', { read: ViewContainerRef }) private container: ViewContainerRef

  constructor(private componentFactoryResolver: ComponentFactoryResolver) {}

  ngOnInit() {
    // Prepare to render the right component
    const component = this.getComponentByType(this.data.type)
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(component)

    // Clear the view before rendering the component
    const viewContainerRef = this.container
    viewContainerRef.clear()

    // Create component
    const componentRef = viewContainerRef.createComponent(componentFactory)
    componentRef.instance.data = this.data
  }

  private getComponentByType(type: string) {
    const componentMapByType = { '1': Component1, '2': Component2, '3': Component3 }
    return componentMapByType[type]
  }
}

您應該閱讀本文以了解更多信息: Angular Dynamic Components

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM