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 a <fieldTemplate>.

Я начну исследование, чтобы узнать, может ли быть использование <ng-template #fieldTemplate> жизнеспособным вариантом, тем временем я надеюсь, что кто-то может рассказать о возможности выполнения этой функции с помощью @Pipe.

Ответ 1

После продолжения моего исследования я не смог найти способ реализовать то, что я хочу, с помощью @Pipe, и по уважительной причине: @Pipe не предназначен для работы.

Вместо этого я нашел Angular 4 NgComponentOutlet.

Я начинаю работать с ним, но мой первый пример будет примерно таким:

@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 (см. OP).

Если люди просят его, я могу обновить этот ответ более конкретным и "окончательным" кодом.

Update:

Это будет мой первый подход, чтобы выбрать 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); }
}