Skip to content

Commit

Permalink
fix(grid-list): styles not cleared when switching to a different styl…
Browse files Browse the repository at this point in the history
…ing mode (#6660)

Fixes the old styles not being cleared when switching between styling modes in the grid list (e.g. going for proportions to a fixed height).

Fixes #4047.
  • Loading branch information
crisbeto authored and tinayuangao committed Sep 6, 2017
1 parent d0eef62 commit 87d607e
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 20 deletions.
32 changes: 27 additions & 5 deletions src/lib/grid-list/grid-list.spec.ts
Expand Up @@ -64,13 +64,13 @@ describe('MdGridList', () => {
it('should use a ratio row height if passed in', () => {
let fixture = TestBed.createComponent(GirdListWithRowHeightRatio);

fixture.componentInstance.heightRatio = '4:1';
fixture.componentInstance.rowHeight = '4:1';
fixture.detectChanges();

let tile = fixture.debugElement.query(By.directive(MdGridTile));
expect(getStyle(tile, 'padding-top')).toBe('100px');

fixture.componentInstance.heightRatio = '2:1';
fixture.componentInstance.rowHeight = '2:1';
fixture.detectChanges();

expect(getStyle(tile, 'padding-top')).toBe('200px');
Expand Down Expand Up @@ -257,14 +257,36 @@ describe('MdGridList', () => {
it('should not use calc() that evaluates to 0', () => {
const fixture = TestBed.createComponent(GirdListWithRowHeightRatio);

fixture.componentInstance.heightRatio = '4:1';
fixture.componentInstance.rowHeight = '4:1';
fixture.detectChanges();

const firstTile = fixture.debugElement.query(By.directive(MdGridTile)).nativeElement;

expect(firstTile.style.marginTop).toBe('0px');
expect(firstTile.style.left).toBe('0px');
});

it('should reset the old styles when switching to a new tile styler', () => {
const fixture = TestBed.createComponent(GirdListWithRowHeightRatio);

fixture.componentInstance.rowHeight = '4:1';
fixture.detectChanges();

const list = fixture.debugElement.query(By.directive(MdGridList));
const tile = fixture.debugElement.query(By.directive(MdGridTile));

expect(getStyle(tile, 'padding-top')).toBe('100px');
expect(getStyle(list, 'padding-bottom')).toBe('100px');

fixture.componentInstance.rowHeight = '400px';
fixture.detectChanges();

expect(getStyle(tile, 'padding-top')).toBe('0px', 'Expected tile padding to be reset.');
expect(getStyle(list, 'padding-bottom')).toBe('0px', 'Expected list padding to be reset.');
expect(getStyle(tile, 'top')).toBe('0px');
expect(getStyle(tile, 'height')).toBe('400px');
});

});


Expand Down Expand Up @@ -306,12 +328,12 @@ class GridListWithUnspecifiedRowHeight { }

@Component({template: `
<div style="width:400px">
<md-grid-list cols="1" [rowHeight]="heightRatio">
<md-grid-list cols="1" [rowHeight]="rowHeight">
<md-grid-tile></md-grid-tile>
</md-grid-list>
</div>`})
class GirdListWithRowHeightRatio {
heightRatio: string;
rowHeight: string;
}

@Component({template: `
Expand Down
34 changes: 21 additions & 13 deletions src/lib/grid-list/grid-list.ts
Expand Up @@ -85,8 +85,12 @@ export class MdGridList implements OnInit, AfterContentChecked {
/** Set internal representation of row height from the user-provided value. */
@Input()
set rowHeight(value: string | number) {
this._rowHeight = coerceToString(value);
this._setTileStyler();
const newValue = coerceToString(value);

if (newValue !== this._rowHeight) {
this._rowHeight = newValue;
this._setTileStyler(this._rowHeight);
}
}

ngOnInit() {
Expand All @@ -106,44 +110,48 @@ export class MdGridList implements OnInit, AfterContentChecked {
private _checkCols() {
if (!this.cols) {
throw Error(`md-grid-list: must pass in number of columns. ` +
`Example: <md-grid-list cols="3">`);
`Example: <md-grid-list cols="3">`);
}
}

/** Default to equal width:height if rowHeight property is missing */
private _checkRowHeight(): void {
if (!this._rowHeight) {
this._tileStyler = new RatioTileStyler('1:1');
this._setTileStyler('1:1');
}
}

/** Creates correct Tile Styler subtype based on rowHeight passed in by user */
private _setTileStyler(): void {
if (this._rowHeight === MD_FIT_MODE) {
private _setTileStyler(rowHeight: string): void {
if (this._tileStyler) {
this._tileStyler.reset(this);
}

if (rowHeight === MD_FIT_MODE) {
this._tileStyler = new FitTileStyler();
} else if (this._rowHeight && this._rowHeight.indexOf(':') > -1) {
this._tileStyler = new RatioTileStyler(this._rowHeight);
} else if (rowHeight && rowHeight.indexOf(':') > -1) {
this._tileStyler = new RatioTileStyler(rowHeight);
} else {
this._tileStyler = new FixedTileStyler(this._rowHeight);
this._tileStyler = new FixedTileStyler(rowHeight);
}
}

/** Computes and applies the size and position for all children grid tiles. */
private _layoutTiles(): void {
let tracker = new TileCoordinator(this.cols, this._tiles);
let direction = this._dir ? this._dir.value : 'ltr';
const tracker = new TileCoordinator(this.cols, this._tiles);
const direction = this._dir ? this._dir.value : 'ltr';
this._tileStyler.init(this.gutterSize, tracker, this.cols, direction);

this._tiles.forEach((tile, index) => {
let pos = tracker.positions[index];
const pos = tracker.positions[index];
this._tileStyler.setStyle(tile, pos.row, pos.col);
});

this._setListStyle(this._tileStyler.getComputedHeight());
}

/** Sets style on the main grid-list element, given the style name and value. */
_setListStyle(style: [string, string] | null): void {
_setListStyle(style: [string, string | null] | null): void {
if (style) {
this._renderer.setStyle(this._element.nativeElement, style[0], style[1]);
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/grid-list/grid-tile.ts
Expand Up @@ -52,7 +52,7 @@ export class MdGridTile {
* Sets the style of the grid-tile element. Needs to be set manually to avoid
* "Changed after checked" errors that would occur with HostBinding.
*/
_setStyle(property: string, value: string): void {
_setStyle(property: string, value: any): void {
this._renderer.setStyle(this._element.nativeElement, property, value);
}
}
Expand Down
34 changes: 33 additions & 1 deletion src/lib/grid-list/tile-styler.ts
Expand Up @@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {MdGridList} from './grid-list';
import {MdGridTile} from './grid-tile';
import {TileCoordinator} from './tile-coordinator';

Expand Down Expand Up @@ -139,6 +140,13 @@ export abstract class TileStyler {
* @docs-private
*/
getComputedHeight(): [string, string] | null { return null; }

/**
* Called when the tile styler is swapped out with a different one. To be used for cleanup.
* @param list Grid list that the styler was attached to.
* @docs-private
*/
abstract reset(list: MdGridList);
}


Expand Down Expand Up @@ -166,6 +174,15 @@ export class FixedTileStyler extends TileStyler {
'height', calc(`${this.getTileSpan(this.fixedRowHeight)} + ${this.getGutterSpan()}`)
];
}

reset(list: MdGridList) {
list._setListStyle(['height', null]);

list._tiles.forEach(tile => {
tile._setStyle('top', null);
tile._setStyle('height', null);
});
}
}


Expand Down Expand Up @@ -203,8 +220,17 @@ export class RatioTileStyler extends TileStyler {
];
}

reset(list: MdGridList) {
list._setListStyle(['padding-bottom', null]);

list._tiles.forEach(tile => {
tile._setStyle('margin-top', null);
tile._setStyle('padding-top', null);
});
}

private _parseRatio(value: string): void {
let ratioParts = value.split(':');
const ratioParts = value.split(':');

if (ratioParts.length !== 2) {
throw Error(`md-grid-list: invalid ratio given for row-height: "${value}"`);
Expand Down Expand Up @@ -237,6 +263,12 @@ export class FitTileStyler extends TileStyler {
tile._setStyle('height', calc(this.getTileSize(baseTileHeight, tile.rowspan)));
}

reset(list: MdGridList) {
list._tiles.forEach(tile => {
tile._setStyle('top', null);
tile._setStyle('height', null);
});
}
}


Expand Down

0 comments on commit 87d607e

Please sign in to comment.