Angular2: заменить элемент узла шаблоном компонента
Я новичок в angular
вообще и angular2
конкретно. Я пытаюсь написать компонент контейнера, в котором должны быть дочерние компоненты.
Например, контейнерный компонент:
@Component({
selector: 'my-list',
template: '
<ul>
<ng-content></ng-content>
</ul>
'
})
export class MyList {
}
Дочерний компонент:
import { Component } from 'angular2/core'
@Component({
selector: 'my-item',
template: '
<li>
<ng-content></ng-content>
</li>
'
})
export class MyItem {
}
Я хотел бы сделать эту структуру:
<my-list>
<my-item>One</my-item>
<my-item>Two</my-item>
</my-list>
Должен быть представлен к следующему:
<my-list>
<ul>
<li>One</li>
<li>Two</li>
</ul>
</my-list>
Но вместо этого у меня есть хост-элемент контейнера и сохраненные элементы:
<my-list>
<ul>
<my-item>
<li>One</li>
</my-item>
<my-item>
<li>Two</li>
</my-item>
</ul>
</my-list>
Plunk доступен здесь
Вопрос: есть ли способ исключить элементы хоста и оставить только обработанный шаблон?
Ответы
Ответ 1
Наконец я нашел решение: MyItem
ElementRef
в MyItem
и использовать его nativeElement.innerHTML
:
MyList:
import { Component, ContentChildren, QueryList } from 'angular2/core'
import { MyItem } from './myitem'
@Component({
selector: 'my-list',
template: '
<ul>
<li *ngFor="#item of items" [innerHTML]="item.innerHTML"></li>
</ul>
'
})
export class MyList {
@ContentChildren(MyItem) items: QueryList<MyItem>
}
MyItem:
import { Directive, Inject, ElementRef } from 'angular2/core'
@Directive({selector: 'my-item'})
export class MyItem {
constructor(@Inject(ElementRef) element: ElementRef) {
this.innerHTML = element.nativeElement.innerHTML
}
}
Работающий планк здесь
Ответ 2
Это вы должны получить то, что вы хотите:
@Component({
selector: 'ul[my-list]',
template: '
<ng-content></ng-content>
'
})
export class MyList {
}
@Component({
selector: 'li[my-item]',
template: '
<ng-content></ng-content>
'
})
export class MyItem {
}
<ul my-list>
<li my-item>One</li my-item>
<li my-item>Two</li my-item>
</li my-list>
Ответ 3
Новые угловые версии имеют действительно классную директиву, которая может быть использована и для вашего случая использования. Tadaa: NgComponentOutlet. Удачного кодирования;)
Пример:
@Component({selector: 'hello-world', template: 'Hello World!'})
class HelloWorld {
}
@Component({
selector: 'ng-component-outlet-simple-example',
template: '<ng-container *ngComponentOutlet="HelloWorld"></ng-container>'
})
class NgTemplateOutletSimpleExample {
// This field is necessary to expose HelloWorld to the template.
HelloWorld = HelloWorld;
}
Ответ 4
Существует хакерское обходное решение, которое может не поддерживаться в старых версиях браузера, но оно работало для моего проекта, и я думаю, что его довольно легко интегрировать без изменения или добавления большого количества кода.
Сначала вам нужно изменить селектор класса/компонента MyItem из селектора элемента
selector: 'custom-element-name'
для атрибута селектора
selector: '[customAttributeName]'
и, наконец, используйте элемент слота html, чтобы обернуть MyItem внутри html-шаблона MyList
<slot customAttributeName></slot>
Полный код:
import { Component } from 'angular2/core'
@Component({
selector: 'my-list',
template: '
<ul>
<slot myItemAsAtribute></slot>
</ul>
'
})
export class MyList {
}
@Component({
selector: '[myItemAsAtribute]',
template: '
<li *ngFor="let item of items">{{item}}</li>
'
})
export class MyItem {
}
Ответ 5
В последней версии вы даже можете не добавлять <ng-content></ng-content>
Я применил это как:
import {Component} from '@angular/core';
@Component({
selector: 'div[app-root]',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css']
})
export class AppComponent {
title = 'Delegates Presence Reporting';
}
и шаблон:
<div class="centered">
<h1>{{title}}</h1>
</div>
index.html
<body>
<div app-root></div>
</body>