Angular2:使用管道动态渲染模板 [英] Angular2: Use Pipe to render templates dynamically

查看:153
本文介绍了Angular2:使用管道动态渲染模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个表单,用于从后端获取字段.映射后,我有类似这样的内容:

I am creating a form where I get the fields from the backend. After mapping, I have something like this:

genericFilters: {
        iboId: {
            'display': false,
            'template': ''
        },
        iboCode: {
            'display': true,
            'template': 'text_input_iboCode',
            /*'template': 'text/iboCode'*/
        },
        iboName: {
            'display': true,
            'template': 'text_input_iboName'
        },
        iboSurname: {
            'display': true,
            'template': 'text_input_iboSurname'
        },
        iboRank: {
            'display': false,
            'template': 'multiselect_iboRank',
            /*'template': 'select/multi_iboRank',*/
        },
        iboEmail: {
            'display': false,
            'template': 'text_input_iboEmail'
        },
        iboNewsletter: {
            'display': true,
            'template': 'simple_select_iboNewsletter',
            /*'template': 'select/simple_iboNewsletter',*/
        },
    };

我背后的想法是在应用程序级别为表单字段创建每种字段类型(checkboxmultiselecttextradio等).并使用上面映射的JSON将某种字段类型应用于从后端接收到的每个字段.

My idea behind this is to create each field type (checkbox, multiselect, text, radio, etc.) for the form field at an app level. And use the mapped JSON above to apply a certain field type to every receieved field from the back end.

在我的示例中,字段iboId应该具有字段类型<text_input_iboCode>.

In my example, the field iboId should have the field type <text_input_iboCode>.

所以,在我看来,我不想有这样的东西:

So, in my view, I don't want to have something like this:

<text_input_iboCode></text_input_iboCode>
<text_input_iboName></text_input_iboName>
<text_input_iboSurname></text_input_iboSurname>

我实际上希望表单创建更加抽象,像这样:

I would actually like to have the form creation more abstract, something like this:

<div *ngFor="let field of genericFilters | dynamicTemplateProcessorPipe">
    {{field.template}} <!--This should equal '<text_input_iboName>' for example-->
</div>

问题:

我要月亮吗?这有可能吗?是否有其他或更好的方法来实现这一目标?我在滥用@Pipe功能吗?

Am I asking for the moon? Is this even possible? Are there other or better approaches to achieve this? Am I abusing the @Pipe functionality?

我实际上是在使用@Pipe进行翻译,格式化,在模板中循环浏览objects等.我猜我也可以将它们用于return<fieldTemplate>.

I am actually using @Pipe for translations, formatting, looping through objects in templates, etc. I guessed I could also use them to return a <fieldTemplate>.

我将开始研究,以查看使用<ng-template #fieldTemplate>是否也可能是可行的选择,与此同时,我希望有人可以通过@Pipe了解此功能的可行性.

I will start a research to see if the usage of <ng-template #fieldTemplate> could also be a viable option, in the meanwhile I hope someone could lay some light on the doability of this functionality with @Pipe.

推荐答案

在继续我的研究之后,我找不到用@Pipe实现我想要的东西的方法,并且有充分的理由:@Pipe并不意味着那样工作.

After continuing my research I could not find out a way of implementing what I want with @Pipe, and for a good reason: @Pipe is not meant to work like that.

我发现Angular 4的 NgComponentOutlet .

I found instead Angular 4's NgComponentOutlet.

我开始使用它,但是我的第一个示例将是这样的:

I am starting to work with it, but my first example would be something like this:

@Component({selector: 'text-input-ibo-name', template: '<input type="text" name="ibo_name">'})
class TextIboName {
}
@Component({
  selector: 'ng-my-form',
  template: `<ng-container *ngComponentOutlet="TextIboName"></ng-container>`
})
class NgMyForm {
  // This field is necessary to expose HelloWorld to the template.
  TextIboName = TextIboName;
}

这是基础.现在,我只需要查看如何在*ngFor中应用<ng-container *ngComponentOutlet="TextIboName"></ng-container>(请参阅OP).

This is the basis. Now I just need to see how to apply <ng-container *ngComponentOutlet="TextIboName"></ng-container> in my *ngFor (see OP).

如果人们要求,我可以使用更具体的最终"代码来更新此答案.

If people request it, I can update this answer with more concrete and 'final' code.

更新:

这是我为映射的JSON上声明的字段选择template的第一种方法.

This would be my first approach to select the template for that field that is declared on the mapped JSON.

<div *ngFor="let field of genericFilters | dynamicTemplateProcessorPipe">
    <ng-container *ngComponentOutlet="{{field.template}}"></ng-container>
</div>

TextIboNameTextIboCodeTextIboSurname等.将在公用文件夹中声明,并导入到当前的component中,只是为了采用更抽象的方法.

The classes TextIboName, TextIboCode, TextIboSurname, etc. Will be declared in a common folder and imported to the current component, just to have a more abstract approach.

目标是能够在所有应用中重用这些字段.这样,我将能够在其他地方复制TextIboName字段,而不必复制/粘贴 HTML代码或templates.

The goal is to be able to reuse these fields throughout all the App. Like this, I will be able to replicate the field TextIboName in other places without having to Copy/Paste HTML code or templates.

更新2:

如果我们将字段组件"移动,在我的示例中将是TextIboName到另一个@ngModule中的外部文件夹,或者我们只想使用另一个@ngModule中的外部类,则必须使用 NgModuleFactory .

If we move our 'field component', in my example would be TextIboName to an external folder within another @ngModule or we simply want to use an external class from another @ngModule we will have to use NgModuleFactory.

上面的代码经过修改:

@Component({
  selector: 'ng-my-form',
  template: `
    <ng-container *ngComponentOutlet="TextIboName;
                                      ngModuleFactory: myModule;"></ng-container>`
})
class NgMyForm {
  // This field is necessary to expose OtherModuleComponent to the template.
  TextIboName = TextIboName;
  myModule: NgModuleFactory<any>;
  constructor(compiler: Compiler) { this.myModule = compiler.compileModuleSync(OtherModule); }
}

这篇关于Angular2:使用管道动态渲染模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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