Подтвердить что ты не робот

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 доступен здесь

Вопрос: есть ли способ исключить элементы хоста и оставить только обработанный шаблон?

4b9b3361

Ответ 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>