Angular2: использование Pipe для динамического рендеринга шаблонов
Я создаю форму, где я получаю поля из бэкэнда. После сопоставления у меня что-то вроде этого:
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',*/
},
};
Моя идея заключается в том, чтобы создать каждый тип поля (checkbox
, multiselect
, text
, radio
и т. д.) для поля формы на уровне приложения. И использовать сопоставленный JSON
выше, чтобы применить определенный тип поля к каждому полученному полю от серверной части.
В моем примере поле iboId
должен иметь тип поля <text_input_iboCode>
,
Так что, на мой взгляд, я не хочу иметь что-то вроде этого:
<text_input_iboCode></text_input_iboCode>
<text_input_iboName></text_input_iboName>
<text_input_iboSurname></text_input_iboSurname>
Я бы хотел, чтобы создание формы было более абстрактным, примерно так:
<div *ngFor="let field of genericFilters | dynamicTemplateProcessorPipe">
{{field.template}} <!--This should equal '<text_input_iboName>' for example-->
</div>
Вопросы:
Я спрашиваю о луне? Это вообще возможно? Есть ли другие или лучшие подходы для достижения этой цели? Я злоупотребляю @Pipe
функциональность?
Я на самом деле использую @Pipe
для переводов, форматирования, циклического просмотра objects
в шаблонах и т. д. Я догадался, что я мог бы также использовать их для return
<fieldTemplate>
,
Я начну исследование, чтобы увидеть, если использование <ng-template #fieldTemplate>
также может быть жизнеспособным вариантом, в то же время я надеюсь, что кто-то мог бы пролить свет на выполнимость этой функциональности с @Pipe
,
1 ответ
После продолжения моего исследования я не смог найти способ реализовать то, что я хочу с @Pipe
и по уважительной причине: @Pipe
не предназначен для такой работы.
Я нашел вместо NgComponentOutlet Angular 4.
Я начинаю работать с ним, но мой первый пример будет примерно таким:
@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;
}
Это основа. Теперь мне просто нужно посмотреть, как подать заявку <ng-container *ngComponentOutlet="TextIboName"></ng-container>
в моем *ngFor
(см. ОП).
Если люди попросят об этом, я могу дополнить этот ответ более конкретным и "окончательным" кодом.
Обновить:
Это будет мой первый подход к выбору template
для того поля, которое объявлено на карте JSON
,
<div *ngFor="let field of genericFilters | dynamicTemplateProcessorPipe">
<ng-container *ngComponentOutlet="{{field.template}}"></ng-container>
</div>
Классы TextIboName
, TextIboCode
, TextIboSurname
и т. д. будут объявлены в общей папке и импортированы в текущую component
просто чтобы иметь более абстрактный подход.
Цель состоит в том, чтобы иметь возможность повторно использовать эти поля во всем приложении. Как это, я смогу повторить поле TextIboName
в других местах без необходимости копирования / вставки HTML
код или templates
,
Обновление 2:
Если мы переместим наш "компонент поля", в моем примере будет TextIboName
во внешнюю папку внутри другой @ngModule
или мы просто хотим использовать внешний класс из другого @ngModule
нам придется использовать 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); }
}