繁体   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