问题
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