角动态分量加载

时间:2017-02-28 13:45:09

标签: angular angular-components

我正在学习Angular,我有一个带有API的CMS,它返回页面的内容。页面可以包含表单的简短代码,我已经更新了API以使用组件选择器

替换short

示例页面内容看起来像

<div>bla bla bla </div>
<app-form [id]="1"></app-form>

在角度我已经创建了FormComponent来相应地加载表单,但是当我用上面提到的选择器获取页面内容时我得到了错误

&#39; APP-形式&#39;不是一个已知的元素:.....

我做了一些研究,发现我需要一些动态组件加载器,但根据我的情况找不到任何有用的例子,任何人都可以帮我解决这个问题

1 个答案:

答案 0 :(得分:1)

实际上,您必须动态创建这些组件。请参阅此plunkr以获取执行此操作的示例代码:https://plnkr.co/edit/kkM1aR4yPcIqeBhamoDW?p=info

虽然您需要ViewContainer for Angular来知道插入该动态组件的位置。这不起作用,因为您无法绑定到innerHTML,然后手动更改innerHTML的代码。我不确定,但我认为这会破坏角度变化检测。

几个月前我不得不这样做,并想出了一个解决方案。我想在此提及我现在还不确定是否有更好的解决方案。无论如何,我所做的不是创建动态组件,而是使用* ngIfs创建一些自定义渲染。 让我解释一下:您的内容包含标签。您可以决定这些标签的外观。 在我的例子中,我有一个标签,用户可以在任何他想要的地方插入:[galerie="key_of_gallery"]。 所以内容可能看起来像

some normal text
 <h2>Oh what a nice heading</h2>
 [galerie="summer_gallery"]
 text again

现在我该怎么渲染呢? 我必须得到像

这样的东西
 <div>
    some normal text
    <h2>Oh what a nice heading</h2>
 </div>
 <galerie [key]="summer_gallery"></galerie>
 <div>
     text again
 </div>

所以我创建了一个自定义组件来创建它:

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

@Component({
    selector: 'ffam-render-key-value',
    template: `<div *ngFor="let contentToRender of contentArray">
                    <div *ngIf="contentToRender.type==='normal'" [innerHTML]="contentToRender.value">
                    </div>
                    <galerie *ngIf="contentToRender.type==='gallery'" [key]="contentToRender.key"></galerie>
                </div>`
})
export class NoeRenderKeyValueComponent{
    @Input('contentArray') contentArray: any[] = [];
}

所有这些组件需要的是一个标签数组,它们将使用* ngFor进行渲染。根据标记的类型,可以创建普通HTML或组件。

此组件可以像

一样插入
    <ffam-render-key-value [contentArray]="keyValues['_text'].arrayWithCustomTags">
    </ffam-render-key-value>

为了获得这个标签数组,我创建了一个带有函数的服务:

public getArrayWithCustomTags(keyValue): any[] {
        let arrayWithCustomTags: any[] = [];
        //check if custom Tag exists in the innerHTML
        if (keyValue.value.indexOf('[galerie=') !== -1) {
            //replace double quotes
            keyValue.value = keyValue.value.replace(/&quot;/g, '"');
            //it exists, get array of all tags
            //regex that matches all [galerie="SOME KEY"] or [someAttribute="some text here"] -> You have to change this regex to fit all your tags
            let pattern = /(?:(\[galerie=\"[^\"]+\"\]))+/;
            //split with regexp to get array
            let arrayOfContents: string[] = keyValue.value.split(new RegExp(pattern, 'gi'));
            for (let i = 0; i < arrayOfContents.length; i++) {
                if (typeof arrayOfContents[i] === "undefined") {
                    arrayOfContents.splice(i, 1);
                    i--;
                }
                else {
                    let customTagToBeInserted: any = {};
                    if (arrayOfContents[i].indexOf('[galerie=') !== -1) {
                        //custom tag gallery
                        customTagToBeInserted.type = "gallery";
                        //get key only
                        customTagToBeInserted.key = arrayOfContents[i].replace("[galerie=\"", "").replace("\"]", "");
                    }
                    //else if some other attribute or even create a switch () {}
                    else {
                        //insert the normalHtml sanitized
                        customTagToBeInserted.type = "normal";
                        customTagToBeInserted.value = this.sanitizer.bypassSecurityTrustHtml(arrayOfContents[i]);
                    }
                    arrayWithCustomTags.push(customTagToBeInserted);
                }
            }
        }
        else {
            arrayWithCustomTags.push({ type: "normal", value: this.sanitizer.bypassSecurityTrustHtml(keyValue.value)});
        }
        return arrayWithCustomTags;
    }

这将创建一个类似的数组:

[0]: {type: "normal", value:"SecureHTML"},
[1]: {type: "gallery", key:"summer_gallery"},
[2]: {type: "normal", value:"SecureHTML"},

嗯,我觉得你明白了。 如果您创建一个包含更多标签的整个CMS,我建议您创建一个功能,可以轻松地为标签创建整个过程(正则表达式等)。 此示例代码仅适用于一个标记。

结果是组件呈现在用户放置它们的位置。 我希望这会对你有所帮助。

顺便说一句,如果您有可编辑的键值对,您可能会发现这有用:https://github.com/bergben/ng2-ck-editable。这是我构建的一个小模块,可以使用ck编辑器对任何div进行编辑。