角度-网格列表不显示由< ng-content>传递的子代 [英] Angular - mat-grid-list not displaying children passed by <ng-content>

查看:79
本文介绍了角度-网格列表不显示由< ng-content>传递的子代的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用角形材料设计组件,并希望创建一个自定义网格列表组件.该组件将根据其大小调整网格列表列的数量.组件模板如下所示:

I'm using angular material design components and want to create a custom grid-list component. The component would adapt the number of grid-list-columns based on its size. The components template would look like this:

<mat-grid-list [cols]="adaptiveCols">
    <ng-content></ng-content>
</mat-grid-list>

该组件将像这样使用:

<my-grid>
    <mat-grid-tile>tile_content</mat-grid-tile>
    <mat-grid-tile>tile_content</mat-grid-tile>
    <mat-grid-tile>tile_content</mat-grid-tile>
</my-grid>

因此,您会认为这将显示其中包含3个<mat-grid-tile><mat-grid-list>,并且结果DOM将包含这些元素.但是您看不到图块或它们的内容.

So you would think this would display a <mat-grid-list> with 3 <mat-grid-tile>s in them, and the resulting DOM will contain those elements. But you don't see the tiles nor their content.

向网格列表中添加更多图块并使用固定的rowHeight不会影响网格列表的height属性(据我所知,网格列表会根据网格的高度来计算其高度瓷砖的数量和颜色/行跨度).这使您认为网格列表没有看到" <mat-grid-tile>-子级.查看源代码网格列表并在_layoutTiles()上设置断点,确认了这一点,在此方法中,this._tiles为空.
我的猜测是角度ContentChildren-注释(在此)在第一个代码段中找不到平铺子对象,因为它仅适用于DOM的第一级,而在第一级中,我们只有<ng-content>.

Adding more tiles to the grid-list and using a fixed rowHeight doesn't affect the height-attribute of the grid-list (from what I could figure out the grid-list calculates its height based on the number and col-/rowspan of tiles). That makes you think the grid-list doesn't "see" the <mat-grid-tile>-children. Looking at the source code of the grid-list and setting a breakpoint on _layoutTiles() confirmed this, in this method this._tiles is empty.
My guess is the angular ContentChildren-annotation (here) doesn't find the tile-children in the first code snippet because it only works on the first level of DOM, and that first level we only have the <ng-content>.

期望的结果很明确,我希望能够使用自定义的网格列表组件,为其添加一些子代并使用其功能.但是由于某种原因,angular不想让我成功,或者我仍然有很多东西要学习.

The desired result is clear, I want to be able to use a custom grid-list component, give it some children and use its features. But for some reason, angular doesn't want me to succeed, or I still have the stuff to learn.

我正在使用angular 6.1,并使用官方文档安装了材料组件.

I'm using angular 6.1 and installed the material-components using the official docs.

推荐答案

mat-grid-list在其自己的实现中使用内容投影,因此它需要能够查询其投影内容.尝试添加另一级别的内容投影将使此操作无法实现,因为mat-grid-tile并不是由列表而是由您的组件实际投影的.

mat-grid-list uses content projection in it's own implementation and so it needs to be able to query it's projected content. Trying to add another level of content projection makes this not possible since the mat-grid-tile's are not actually being projected by the the list, but by your component.

这么短的答案:这行不通.

So short answer: this isn't gona work.

可能有一种方法可以实现您的目标,但内容投影却不是.如果您能澄清一下您的意图,我可能会提供帮助.您仍然需要使用模板.

There is likely a way to achieve your goal but content projection isn't the way. If you clarify your intentions a bit, I may be able to help. You likley need to use templates though.

这是简单的情况:在mat-grid-list周围编写包装器,该包装器接受数据数组作为输入,您可以使用ngFor进行迭代以创建图块

Here's the simple case: write a wrapper around mat-grid-list that accepts an array of data as input that you can iterate over with ngFor to create the tiles

@Component({
  selector: 'my-grid',
  templateUrl: './my-grid.html'
})
export class MyGrid {
  @Input() data: string[];
}


<mat-grid-list>
  <mat-grid-tile *ngFor="let d of data">{{d}}</mat-grid-tile>
</mat-grid-list>

这为mat-grid-list提供了一个可重用的包装器,为您抽象了一些包装.但是,如果网格内容比字符串复杂(可能)或在每次使用时都需要自定义模板,那么这样做就不好了.在这种情况下,您需要使用模板和指令的更为精细的方法:

This provides a reusable wrapper around mat-grid-list that abstracts a bit of it away for you. however, this is no good if your grid content is more complex than a string (likely) or requires custom templates on every usage. In this case, you need a somewhat more refined approach, using templates and directives:

@Directive({
  selector: 'gridTemplate'
})
export class GridTemplate {
   @Input() key: string;
   constructor(private elementRef: ElementRef, public template: TemplateRef<any>) {}
}

此指令将标识您的自定义模板,然后在网格列表中,您可以使用这些模板来填充图块

This directive will identify your custom templates then, in your grid list, you can use these templates to populate the tiles

@Component({
  selector: 'my-grid',
  templateUrl: './my-grid.html'
})
export class MyGrid implements AfterContentInit {
  //structure the data so it can be assigned to a template by key
  @Input() data: {templateKey:string, data: any}[];

  //use content children to find projected templates
  @ContentChildren(GridTemplate)
  gridTemplates: QueryList<GridTemplate>;

  gridTemplateMap: {[key:string]: TemplateRef<any>} = {};

  ngAfterContentInit() { 
    //store queried templates in map for use in template
    this.gridTemplates.forEach(t => this.gridTemplateMap[t.key] = t.template);
  }
}


<ng-template #defaultGridTemp let-d="data">{{d}}</ng-template>
<mat-grid-list>
  <mat-grid-tile *ngFor="let d of data">
    <!-- here we use the template map to place the correct templates or use a default -->
    <!-- we also feed the data property as context into the template -->
    <ng-container [ngTemplateOutlet]="(gridTemplateMap[d.templateKey] || defaultGridTemp)" 
                  [ngTemplateOutletContext]="{ data: d.data }" ></ng-container>
  </mat-grid-tile>
</mat-grid-list>

然后您对组件的用法如下:

Then your usage of your component is like this:

@Component({...})
export class MyComponent {
   data = [
    { templateKey:'MyKey1', data: {message: 'Projected Message', number: 1} },
    { templateKey:'MyKey2', data: {whatever: 'Message', youWant: 'to place'} }
   ];
}


<my-grid [data]="data">
  <ng-template gridTemplate key="MyKey1" let-d="data">
     <div>{{d.message}}</div>
     <div>{{d.number}}</div>
     <div>Any other arbitrary content</div>
  </ng-template>
  <ng-template gridTemplate key="MyKey2" let-d="data">
     <div>{{d.whatever}}</div>
     <div>{{d.youWant}}</div>
     <div>Any other arbitrary content</div>
  </ng-template>
</my-grid>

使用这种方法,您可以在网格组件中向所需的mat-grid-list添加任何可重用的逻辑,但仍保持向网格提供自定义模板的灵活性.缺点是您必须采取额外的步骤来构造数据以利用这种方法.

with this approach, you can add whatever reusable logic to mat-grid-list you want inside your grid component but still maintain the flexibility of providing custom templates to your grid. The drawback is that you have to take the extra steps to structure your data to take advantage of this approach.

这篇关于角度-网格列表不显示由&lt; ng-content&gt;传递的子代的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆