问题
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',*/
},
};
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.
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>
Questions:
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?
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>.
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.
回答1:
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.
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;
}
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.
Update:
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>
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.
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.
Update 2:
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.
Adapted above code:
@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); }
}
来源:https://stackoverflow.com/questions/43143956/angular2-use-pipe-to-render-templates-dynamically