Javascript Angular2:渲染一个没有包装标签的组件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38716105/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular2 : render a component without its wrapping tag
提问by Greg
I am struggling to find a way to do this. In a parent component, the template describes a table
and its thead
element, but delegates rendering the tbody
to another component, like this:
我正在努力寻找一种方法来做到这一点。在父组件中,模板描述 atable
及其thead
元素,但将渲染委托tbody
给另一个组件,如下所示:
<table>
<thead>
<tr>
<th>Name</th>
<th>Time</th>
</tr>
</thead>
<tbody *ngFor="let entry of getEntries()">
<my-result [entry]="entry"></my-result>
</tbody>
</table>
Each myResult component renders its own tr
tag, basically like so:
每个 myResult 组件呈现自己的tr
标签,基本上是这样的:
<tr>
<td>{{ entry.name }}</td>
<td>{{ entry.time }}</td>
</tr>
The reason I'm not putting this directly in the parent component (avoiding the need for a myResult component) is that the myResult component is actually more complicated than shown here, so I want to put its behaviour in a separate component and file.
我没有将它直接放在父组件中(避免需要 myResult 组件)的原因是 myResult 组件实际上比这里显示的更复杂,所以我想把它的行为放在单独的组件和文件中。
The resulting DOM looks bad. I believe this is because it is invalid, as tbody
can only contain tr
elements (see MDN), but my generated (simplified) DOM is :
生成的 DOM 看起来很糟糕。我相信这是因为它是无效的,因为tbody
只能包含tr
元素(参见 MDN),但我生成的(简化的)DOM 是:
<table>
<thead>
<tr>
<th>Name</th>
<th>Time</th>
</tr>
</thead>
<tbody>
<my-result>
<tr>
<td>Bob</td>
<td>128</td>
</tr>
</my-result>
</tbody>
<tbody>
<my-result>
<tr>
<td>Lisa</td>
<td>333</td>
</tr>
</my-result>
</tbody>
</table>
Is there any way we can get the same thing rendered, but without the wrapping <my-result>
tag, and while still using a component to be sole responsible for rendering a table row ?
有没有什么办法可以让我们渲染同样的东西,但没有包装<my-result>
标签,同时仍然使用一个组件来单独负责渲染表格行?
I have looked at ng-content
, DynamicComponentLoader
, the ViewContainerRef
, but they don't seem to provide a solution to this as far as I can see.
我已经看过ng-content
, DynamicComponentLoader
, the ViewContainerRef
,但据我所知,他们似乎没有提供解决方案。
采纳答案by Günter Z?chbauer
You can use attribute selectors
您可以使用属性选择器
@Component({
selector: '[myTd]'
...
})
and then use it like
然后像这样使用它
<td myTd></td>
回答by Slim
You need "ViewContainerRef" and inside my-result component do something like this:
您需要“ViewContainerRef”并在 my-result 组件中执行以下操作:
html:
html:
<ng-template #template>
<tr>
<td>Lisa</td>
<td>333</td>
</tr>
</ng-template>
ts:
ts:
@ViewChild('template') template;
constructor(
private viewContainerRef: ViewContainerRef
) { }
ngOnInit() {
this.viewContainerRef.createEmbeddedView(this.template);
}
回答by Shlomi Aharoni
Use this directive on your element
在您的元素上使用此指令
@Directive({
selector: '[remove-wrapper]'
})
export class RemoveWrapperDirective {
constructor(private el: ElementRef) {
const parentElement = el.nativeElement.parentElement;
const element = el.nativeElement;
parentElement.removeChild(element);
parentElement.parentNode.insertBefore(element, parentElement.nextSibling);
parentElement.parentNode.removeChild(parentElement);
}
}
Example usage:
用法示例:
<div class="card" remove-wrapper>
This is my card component
</div>
and in the parent html you call card element as usual, for example:
在父 html 中,您像往常一样调用 card 元素,例如:
<div class="cards-container">
<card></card>
</div>
The output will be:
输出将是:
<div class="cards-container">
<div class="card" remove-wrapper>
This is my card component
</div>
</div>
回答by Nicholas Murray
Attribute selectors are the best way to solve this issue.
属性选择器是解决这个问题的最好方法。
So in your case:
所以在你的情况下:
<table>
<thead>
<tr>
<th>Name</th>
<th>Time</th>
</tr>
</thead>
<tbody my-results>
</tbody>
</table>
my-results ts
我的结果 ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'my-results, [my-results]',
templateUrl: './my-results.component.html',
styleUrls: ['./my-results.component.css']
})
export class MyResultsComponent implements OnInit {
entries: Array<any> = [
{ name: 'Entry One', time: '10:00'},
{ name: 'Entry Two', time: '10:05 '},
{ name: 'Entry Three', time: '10:10'},
];
constructor() { }
ngOnInit() {
}
}
my-results html
我的结果 html
<tr my-result [entry]="entry" *ngFor="let entry of entries"><tr>
my-result ts
我的结果 ts
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: '[my-result]',
templateUrl: './my-result.component.html',
styleUrls: ['./my-result.component.css']
})
export class MyResultComponent implements OnInit {
@Input() entry: any;
constructor() { }
ngOnInit() {
}
}
my-result html
我的结果 html
<td>{{ entry.name }}</td>
<td>{{ entry.time }}</td>
See working stackblitz: https://stackblitz.com/edit/angular-xbbegx
查看工作堆栈闪电战:https://stackblitz.com/edit/angular-xbbegx
回答by robert king
you can try use the new css display: contents
你可以尝试使用新的 css display: contents
here's my toolbar scss:
这是我的工具栏 scss:
:host {
display: contents;
}
:host-context(.is-mobile) .toolbar {
position: fixed;
/* Make sure the toolbar will stay on top of the content as it scrolls past. */
z-index: 2;
}
h1.app-name {
margin-left: 8px;
}
and the html:
和 html:
<mat-toolbar color="primary" class="toolbar">
<button mat-icon-button (click)="toggle.emit()">
<mat-icon>menu</mat-icon>
</button>
<img src="/assets/icons/favicon.png">
<h1 class="app-name">@robertking Dashboard</h1>
</mat-toolbar>
and in use:
并在使用中:
<navigation-toolbar (toggle)="snav.toggle()"></navigation-toolbar>
回答by mjswensen
Another option nowadays is the ContribNgHostModule
made available from the @angular-contrib/common
package.
现在的另一种选择是ContribNgHostModule
从@angular-contrib/common
包中提供。
After importing the module you can add host: { ngNoHost: '' }
to your @Component
decorator and no wrapping element will be rendered.
导入模块后,您可以添加host: { ngNoHost: '' }
到@Component
装饰器中,并且不会呈现任何包装元素。