fix(grid-list): incorrectly laying out tiles for nested list (#13086)

Fixes the grid list picking up the tiles of other nested grid lists, causing them to not being laid out correctly.

Fixes #13074.
This commit is contained in:
Kristiyan Kostadinov
2018-10-02 22:32:42 +02:00
committed by vivian-hu
parent 3c55caaf1e
commit 3e1cff0618
5 changed files with 72 additions and 10 deletions
+25
View File
@@ -0,0 +1,25 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {InjectionToken} from '@angular/core';
/**
* Injection token used to provide a grid list to a tile and to avoid circular imports.
* @docs-private
*/
export const MAT_GRID_LIST = new InjectionToken<MatGridListBase>('MAT_GRID_LIST');
/**
* Base interface for a `MatGridList`.
* @docs-private
*/
export interface MatGridListBase {
cols: number;
gutterSize: string;
rowHeight: number | string;
}
+28
View File
@@ -139,6 +139,18 @@ describe('MatGridList', () => {
expect(getStyle(tiles[2], 'top')).toBe('101px');
});
it('should lay out the tiles correctly for a nested grid list', () => {
const fixture = createComponent(NestedGridList);
fixture.detectChanges();
const innerTiles = fixture.debugElement.queryAll(
By.css('mat-grid-tile mat-grid-list mat-grid-tile'));
expect(getStyle(innerTiles[0], 'top')).toBe('0px');
expect(getStyle(innerTiles[1], 'top')).toBe('101px');
expect(getStyle(innerTiles[2], 'top')).toBe('202px');
});
it('should set the gutter size if passed', () => {
const fixture = createComponent(GridListWithGutterSize);
fixture.detectChanges();
@@ -635,3 +647,19 @@ class GridListWithRtl { }
`
})
class GridListWithIndirectTileDescendants {}
@Component({template: `
<div style="width:200px">
<mat-grid-list cols="2" rowHeight="100px">
<mat-grid-tile></mat-grid-tile>
<mat-grid-tile>
<mat-grid-list cols="1" rowHeight="100px">
<mat-grid-tile></mat-grid-tile>
<mat-grid-tile></mat-grid-tile>
<mat-grid-tile></mat-grid-tile>
</mat-grid-list>
</mat-grid-tile>
</mat-grid-list>
</div>`})
class NestedGridList { }
+11 -4
View File
@@ -23,6 +23,7 @@ import {TileCoordinator} from './tile-coordinator';
import {TileStyler, FitTileStyler, RatioTileStyler, FixedTileStyler} from './tile-styler';
import {Directionality} from '@angular/cdk/bidi';
import {coerceNumberProperty} from '@angular/cdk/coercion';
import {MAT_GRID_LIST, MatGridListBase} from './grid-list-base';
// TODO(kara): Conditional (responsive) column count / row size.
@@ -40,10 +41,14 @@ const MAT_FIT_MODE = 'fit';
host: {
'class': 'mat-grid-list',
},
providers: [{
provide: MAT_GRID_LIST,
useExisting: MatGridList
}],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class MatGridList implements OnInit, AfterContentChecked {
export class MatGridList implements MatGridListBase, OnInit, AfterContentChecked {
/** Number of columns being rendered. */
private _cols: number;
@@ -139,16 +144,18 @@ export class MatGridList implements OnInit, AfterContentChecked {
/** Computes and applies the size and position for all children grid tiles. */
private _layoutTiles(): void {
if (!this._tileCoordinator) {
this._tileCoordinator = new TileCoordinator(this._tiles);
this._tileCoordinator = new TileCoordinator();
}
const tracker = this._tileCoordinator;
const tiles = this._tiles.filter(tile => !tile._gridList || tile._gridList === this);
const direction = this._dir ? this._dir.value : 'ltr';
this._tileCoordinator.update(this.cols);
this._tileCoordinator.update(this.cols, tiles);
this._tileStyler.init(this.gutterSize, tracker, this.cols, direction);
this._tiles.forEach((tile, index) => {
tiles.forEach((tile, index) => {
const pos = tracker.positions[index];
this._tileStyler.setStyle(tile, pos.row, pos.col);
});
+6 -1
View File
@@ -11,14 +11,17 @@ import {
ViewEncapsulation,
ElementRef,
Input,
Optional,
ContentChildren,
QueryList,
AfterContentInit,
Directive,
ChangeDetectionStrategy,
Inject,
} from '@angular/core';
import {MatLine, MatLineSetter} from '@angular/material/core';
import {coerceNumberProperty} from '@angular/cdk/coercion';
import {MAT_GRID_LIST, MatGridListBase} from './grid-list-base';
@Component({
moduleId: module.id,
@@ -36,7 +39,9 @@ export class MatGridTile {
_rowspan: number = 1;
_colspan: number = 1;
constructor(private _element: ElementRef<HTMLElement>) {}
constructor(
private _element: ElementRef<HTMLElement>,
@Optional() @Inject(MAT_GRID_LIST) public _gridList?: MatGridListBase) {}
/** Amount of rows that the grid tile takes up. */
@Input()
+2 -5
View File
@@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
import {QueryList} from '@angular/core';
import {MatGridTile} from './grid-tile';
/**
@@ -53,19 +52,17 @@ export class TileCoordinator {
/** The computed (row, col) position of each tile (the output). */
positions: TilePosition[];
constructor(private _tiles: QueryList<MatGridTile>) {}
/**
* Updates the tile positions.
* @param numColumns Amount of columns in the grid.
*/
update(numColumns: number) {
update(numColumns: number, tiles: MatGridTile[]) {
this.columnIndex = 0;
this.rowIndex = 0;
this.tracker = new Array(numColumns);
this.tracker.fill(0, 0, this.tracker.length);
this.positions = this._tiles.map(tile => this._trackTile(tile));
this.positions = tiles.map(tile => this._trackTile(tile));
}
/** Calculates the row and col position of a tile. */