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); }
}
Другие вопросы по тегам