我正在构建一个角度组件doc / demo站点,它列举了一个Angular组件列表和一组带有使用细节和示例的JSON文档 .
这是一个基本组件的示例:
import { Component } from '@angular/core';
@Component({
selector: 'my-button',
template: `<button class="btn btn-default">I am a banana</button>`
})
export class Button {}
首先,我使用预构建脚本自动生成如下所示的 componentLoader
文件:
import { Route } from '@angular/router';
import { Button } from '../app/components/elements/button/button';
export const COMPONENT_ROUTES: Route[] = [{ path: 'button', component: Button }];
export const COMPONENT_DECLARATIONS: Array<any|any[]> = [Button];
然后我将其加载到 app.module.ts
(为简洁起见,删除了其他导入):
import { COMPONENT_ROUTES, COMPONENT_DECLARATIONS } from './componentLoader';
// ...
@NgModule({
...
declarations: [ ... ].concat(COMPONENT_DECLARATIONS)
这很好用;我可以在视图组件中使用该按钮:
import { Component } from '@angular/core';
@Component({
selector: 'button-test',
template: `
<my-button></my-button>
`
})
export class ButtonTest {}
呜!
现在,我希望能够枚举JSON文档的文件夹,以查找与此组件及其使用方式相关的详细信息 . JSON看起来像这样:
{
"name": "button",
"description": "An example of an 'I am a banana' button",
"exampleHTML": "<div><my-button></my-button></div>"
}
请注意 exampleHTML
中我是如何尝试使用 componentLoader
中加载的组件 .
为了生成文档视图,我构建了一个docs服务,该服务采用 id
param并在/ docs目录中搜索匹配的JSON文档:
import {Injectable} from '@angular/core';
declare const require: any;
@Injectable()
export class DocsService {
constructor() { }
getDoc(id: string) {
const json: string = require('../docs/' + id + '.json');
return json;
}
}
然后,detail组件导入服务并使用模板中的JSON doc组件:
import { Component } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { DocsService } from '../../services/docs.service';
declare const require: any;
const template: string = require('./componentDetail.html');
@Component({
selector: 'componentDetail',
template: `<div>Name: {{componentDoc.name}}</div>
Examples:<br><br><div [innerHTML]="componentExample"></div>`
})
export class ComponentDetail {
public componentDoc: any
private _componentExample: string
public get componentExample(): SafeHtml {
return this._sanitizer.bypassSecurityTrustHtml(this._componentExample);
}
constructor(
private route: ActivatedRoute,
private docsService: DocsService,
private _sanitizer: DomSanitizer
) {
this.route.params.forEach((params: Params) => {
if (params['id'] !== undefined) {
let id = params['id'];
this.componentDoc = this.docsService.getDoc(id)
this._componentExample = this.componentDoc.exampleHTML
} else { throw Error('Not found') }
});
}
}
The problem:
也许是因为这些组件的加载方式,或者因为我正确的模板引擎,或者因为在构建链的中间运行了一个黑盒Webpack服务,应该显示实际 button
组件的模板完全是空白 .
在组件详细信息视图中,我可以手动将模板字符串设置为 <my-button></my-button>
并且它可以正常工作,但是当我尝试从JSON doc加载它时它不会 .
How can I get the detail component to actually render the Button component used in the JSON doc?
1 回答
See working Plnkr Here
您可以通过创建动态组件来解决问题,而不是使用
[innerHTML]
指令 .为此,您需要使用Compiler.compileModuleAndAllComponentsAsync方法动态加载模块及其组件 .
首先,您需要创建一个模块,其中包含您希望能够在动态HTML中使用的应用程序组件 .
将
componentLoader
更改为这样的模块创建将用于生成动态模块和组件的
dynamicComponent.service.ts
. 在动态加载的HTML中使用组件的关键是我们如何在DynamicComponentModule
中导入ComponentsModule
.将
ComponentsModule
和DynamicComponentService
导入app.module.ts
最后,
ComponentDetail
被更改为使用新的DynamicComponentService
来获取动态组件的ComponentFactory
.获得新的
ComponentFactory
后,您可以使用视图容器创建并使用动态html填充组件 .