角动态组件加载 [英] Angular dynamic component loading

查看:51
本文介绍了角动态组件加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am learning Angular, I have a CMS with API that returns contents of pages. pages can have short codes for forms, I have updated the API to replace short with a component selector

示例页面内容如下

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

在angular中,我创建了FormComponent来相应地加载表单,但是当我使用上述选择器获取页面内容时,就会出现错误

In angular I have created FormComponent to load form accordingly, but when I get page contents with above mentioned selector I get the error

"app-form"不是已知元素:.....

'app-form' is not a known element:.....

我进行了一些研究,发现我需要一些动态组件加载器,但根据我的情况找不到任何有效的示例,可以有人帮助我解决此问题吗

I did some research and found that I need some dynamic component loader but could not found any working examples as per my scenario, can any one help on how I can fix this issue

推荐答案

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

Indeed you would have to create those components dynamically. See this plunkr for an example code to do that: https://plnkr.co/edit/kkM1aR4yPcIqeBhamoDW?p=info

尽管您需要一个用于Angular的ViewContainer才能知道在何处插入该动态组件.这将不起作用,因为您无法绑定到innerHTML,然后手动更改innerHTML的代码.我不确定,但我认为这会干扰角度变化检测.

Although you need a ViewContainer for Angular to know where to insert that dynamic component. Which would not work because you can't bind to innerHTML and then change the code of the innerHTML manually. I am not sure but I think that would mess with angulars change detection.

几个月前,我不得不这样做,并提出了一个解决方案.在这一点上,我想指出的是,我不确定目前是否有更好的解决方案.无论如何,我要做的不是创建动态组件,而是使用* ngIfs创建一些自定义渲染. 让我解释一下:您的内容包含标签.您可以决定这些标签的外观. 在我的情况下,我有一个标签,用户可以在任意位置插入它:[galerie="key_of_gallery"]. 所以内容看起来像

I had to do this a few months ago and came up with a solution. I want to mention at this point that I am not sure if there is a better solution to this problem by now. Anyway, what I did is not to create dynamic components but rather create some custom rendering with *ngIfs. Let me explain: Your content contains tags. You decide how those tags look like. In my case I had a tag that the user can insert wherever he wants: [galerie="key_of_gallery"]. So the content could look like

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

现在我该如何渲染呢? 我将不得不得到类似的东西

Now how can I render this? I would have to get something like

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

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

So I created a custom component which creates this:

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或组件.

All this component needs is an array of tags which will be rendered with an *ngFor. Depending on the type of the tag either normal HTML or a component is created.

该组件可以像

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

要获取此标签数组,我创建了具有以下功能的服务:

To get this array of tags I have created a service with a function:

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;
    }

这将创建一个像这样的数组:

This will create an array like:

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

好吧,我想你明白了. 如果您创建带有更多标签的整个CMS,我建议您创建一个可以轻松创建标签整个过程(正则表达式等)的函数. 此示例代码仅用于一个标签.

Well I think you get the idea. If you create a whole CMS with more tags I would recommend creating a function that easily creates this whole process (regex etc.) for a tag. This example code is just meant for one tag.

结果是在用户放置组件的位置正确渲染了组件. 希望对您有帮助.

The result is that the components are rendered right where the user places them. I hope this helps you.

顺便说一句,如果您为用户提供了可编辑的键值对,则可能会有所帮助: https ://github.com/bergben/ng2-ck-editable .我构建了一个小模块,可以使用ck编辑器使所有div可编辑.

Btw, if you have editable key value pairs for the user you might find this helpful: https://github.com/bergben/ng2-ck-editable. It's a little module I built to make any div editable using a ck-editor.

这篇关于角动态组件加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆