Javascript-форум (https://javascript.ru/forum/)
-   Angular.js (https://javascript.ru/forum/angular/)
-   -   Можно ли в pipe отрендерить динамический компонент (Angular2/4)? (https://javascript.ru/forum/angular/71769-mozhno-li-v-pipe-otrenderit-dinamicheskijj-komponent-angular2-4-a.html)

okuznetsov1 11.12.2017 11:50

Можно ли в pipe отрендерить динамический компонент (Angular2/4)?
 
Хотелось бы передать в динамический компонент "tags" параметр "colors[]", затем отрендерить, и полученный результат (сформированный html-шаблон) вернуть в переменной "html".

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
    name: 'tag'
})
export class TagPipe implements PipeTransform {
    constructor(private sanitized: DomSanitizer) {}
    transform(value?: string): any {

        const html = `<tags [colors]="[${value}]"></tags>`;

        return html;
}

destus 11.12.2017 14:08

okuznetsov1,
А нужно ли? Создать динамический компонент не сложно. Достаточно найти фабрику этого компонента и передать её в метод createComponent элемента класса ViewContainerRef. После этого у вас будет ссылка на созданный компонент, через которую и можно передавать инпут параметры
constructor(private componentFactoryResolver: ComponentFactoryResolver) {}
...

createDynamicCompoenent() {
    const value = ['Red', 'Green', 'Blue'];
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory('класс_компонента');
   const cmpRef = vcr.createComponent(factory);
   cmpRef.instance.colors = value;
}


Т.е. обычно такие вещи делают на уровне сервиса / компонента, но никак не на уровне фильтра. Потому что на каждый detectChanges будет создаваться этот самый компонент, что может убить производительность и привести к удивительным результатам.

okuznetsov1 12.12.2017 10:02

Мне кажется вы не совсем правильно меня поняли: динамический компонент у меня создан - это "<tags>", в который передаётся параметр "цвет".

Мне хотелось бы чтобы в теле pipe выполнилось отрендеривание строки:
const html = `<tags [colors]="[${value}]"></tags>`;

в результате после отрендеривания должно получиться к примеру так:
const html = `<span class="no-break">
                    <div class="palette-colors">
                        <div class="row">
                            <div class="col-xs-2 panel-select-color">
                                <div class="row">
                                    <span class="set-color" style="background-color: "#ff0000"; width: "100%"></span>
                                </div>
                            </div>
                        </div>
                    </div>
                </span>`

destus 12.12.2017 10:06

okuznetsov1,
как у вас создается динамический компонент? jsfiddle сделайте, чтобы быстрее разобраться.

okuznetsov1 12.12.2017 10:27

Цитата:

Сообщение от destus (Сообщение 472681)
okuznetsov1,
как у вас создается динамический компонент? jsfiddle сделайте, чтобы быстрее разобраться.

сложновато будет с jsfiddle, нужно подумать как вырезать часть проекта и оформить в jsfiddle.

компонент создан и работает - не в нём дело, сейчас объясню более подробнее.

На данном этапе я сделал pipe, и теперь хочу из данного pipe получить сформированный HTML-код в зависимости от передаваемого в pipe параметра, для этого мне нужно отрендерить динамический компонент.


Возможно существует специально для этого какая-нибудь библиотека, например, можно было сделать так:
constructor(private sanitized: DomRendering) {}
..............
const html = this.sanitized.renderSecurityHtml(`<tags [colors]="[${value}]"></tags>`;


чтобы получить этот html-код:

const html = `<span class="no-break">
                    <div class="palette-colors">
                        <div class="row">
                            <div class="col-xs-2 panel-select-color">
                                <div class="row">
                                    <span class="set-color" style="background-color: "#ff0000"; width: "100%"></span>
                                </div>
                            </div>
                        </div>
                    </div>
                </span>`


Можно конечно здесь в pipe собрать этот template, но мне нужно чтобы был именно компонент, т.к. данный компонент (<tags>) применяется в других модулях/виджитах проекта, при этом в будущем будут создаваться и другие модули с этим компонентом.

destus 12.12.2017 12:34

okuznetsov1,
Просто вставить селектор компонента в DOM и ждать чуда, что Angular заменит его на шаблон компонента не надо. Не будет этого. Динамический компонент создается так, как было написано в посте №2. И всё. Есть ещё ngComponentOutlet, но вам он не подходит, потому что через эту директиву нельзя передавать input и output параметры (есть issue на гитхабе).
https://plnkr.co/edit/oQ9zDzKFDQWakIB4Ithb?p=preview

okuznetsov1 12.12.2017 15:17

Цитата:

Сообщение от destus (Сообщение 472705)
okuznetsov1,
Просто вставить селектор компонента в DOM и ждать чуда, что Angular заменит его на шаблон компонента не надо. Не будет этого. Динамический компонент создается так, как было написано в посте №2. И всё. Есть ещё ngComponentOutlet, но вам он не подходит, потому что через эту директиву нельзя передавать input и output параметры (есть issue на гитхабе).
https://plnkr.co/edit/oQ9zDzKFDQWakIB4Ithb?p=preview

Понял по поводу чуда ещё вчера, поэтому попросил помощи)

Спасибо, в очередной раз мне помогли. Не прислушался к вам вчера, т.к. за плечами ещё небольшой опыт с динамическими компонентами. Не знал как передать переменную, оказалось всё просто:

componentRef.instance.colors = value;
      componentRef.changeDetectorRef.detectChanges();


Часовой пояс GMT +3, время: 06:36.