web-dev-qa-db-fra.com

Angular2: remplace l'élément host par le template du composant

Je suis nouveau à angular en général et à angular2 en particulier. J'essaie d'écrire un composant conteneur, qui devrait contenir des composants enfants. 

Par exemple, composant de conteneur:

@Component({
  selector: 'my-list',
  template: `
    <ul>
      <ng-content></ng-content>
    </ul>
  `
})
export class MyList {
}

Composant enfant:

import { Component } from 'angular2/core'

@Component({
  selector: 'my-item',
  template: `
    <li>
      <ng-content></ng-content>
    </li>
  `
})
export class MyItem {
}

J'aimerais faire cette structure:

<my-list>
    <my-item>One</my-item>
    <my-item>Two</my-item>
</my-list>

A rendre à la suivante:

<my-list>
    <ul>
        <li>One</li>
        <li>Two</li>
    </ul>
</my-list>

Mais au lieu de cela, j'ai l'élément hôte du conteneur et les éléments conservés également:

<my-list>
    <ul>
        <my-item>
            <li>One</li>
        </my-item>
        <my-item>
            <li>Two</li>
        </my-item>
    </ul>
 </my-list>

Plunk est disponible ici

Question: existe-t-il un moyen d'éliminer les éléments Host et de ne laisser que le modèle rendu?

27
Denis Itskovich

Enfin, j'ai trouvé une solution: injecter ElementRef à MyItem et utiliser son nativeElement.innerHTML:

Ma liste:

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
  }
}

Travailler plunk is here

12
Denis Itskovich

Ceci vous devriez obtenir ce que vous voulez:

@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>
13

Les nouvelles versions angulaires ont une directive vraiment cool, qui peut également être utilisée pour votre cas d'utilisation. Tadaa: NgComponentOutlet . Bonne codage;)

Exemple:

@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;
}
3
Luckylooke

Il existe une solution de contournement qui ne sera peut-être pas prise en charge par les anciennes versions de navigateur, mais elle fonctionnait pour le projet minier et je pense qu'il est assez facile de l'intégrer sans modifier ou ajouter beaucoup de code.

Tout d'abord, vous devez changer le sélecteur de MyItem classe/composant à partir de sélecteur d'élément

selector: 'custom-element-name'

à attribut sélecteur

selector: '[customAttributeName]'

et enfin utiliser html slot element pour envelopper MyItem dans MyList modèle html 

<slot customAttributeName></slot>

Code complet:

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 {
}
0
N.Nonkovic