Angular2: replace host element with component's template

China☆狼群 提交于 2019-12-31 08:19:09

问题


I'm new to angular in general and to angular2 specifically. I'm trying to write a container component, which should have child components in it.

For example, container component:

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

Child component:

import { Component } from 'angular2/core'

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

I'd like to make this structure:

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

To be rendered to the following one:

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

But instead, I have the host element of the container and the items preserved as well:

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

Plunk is available here

Question: is there a way to eliminate the host elements and to leave only the rendered template?


回答1:


This you should get what you want:

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



回答2:


Finally I found solution: injecting ElementRef to MyItem and using its 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
  }
}

Working plunk is here




回答3:


New angular versions have really cool directive, which may be used also for your use case. Tadaa: NgComponentOutlet. Happy coding ;)

Example:

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


There is a hacky workaround solution that may not be supported in older browser versions, but it was working for mine project and I think it is quite easy to integrate without changing or adding a lot of code.

First you need to change selector of MyItem class/component from element selector

selector: 'custom-element-name'

to attribute selector

selector: '[customAttributeName]'

and finally use html slot element to wrap MyItem inside MyList html template

<slot customAttributeName></slot>

Full code:

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:


In the latest angular you can even avoid adding <ng-content></ng-content>

I've applied is like:

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

and the template:

<div class="centered">
<h1>{{title}}</h1>
</div>

index.html

<body>
<div app-root></div>
</body>


来源:https://stackoverflow.com/questions/35733699/angular2-replace-host-element-with-components-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!