Responsive Design using md-grid-list in angular 2

Multi tool use
Responsive Design using md-grid-list in angular 2
I am looking at basic example of md-grid-list in Angular 2.
HTML Code :
<md-grid-list cols="4" rowHeight="100px">
<md-grid-tile *ngFor="let tile of tiles"
[colspan]="tile.cols"
[rowspan]="tile.rows"
[style.background]="tile.color">
{{tile.text}}
</md-grid-tile>
</md-grid-list>
TS Code :
export class GridListDynamicExample {
tiles = [
{text: 'One', cols: 3, rows: 1, color: 'lightblue'},
{text: 'Two', cols: 1, rows: 2, color: 'lightgreen'},
{text: 'Three', cols: 1, rows: 1, color: 'lightpink'},
{text: 'Four', cols: 2, rows: 1, color: '#DDBDF1'},
];
}
The above code results in this : How can I make the layout as "column" that is column "Two" to go below the rows(One and Four) on smaller screen size using some HTML directive or CSS?
Angular Material in Angular 1 had option to achieve by specifying "md-cols-xs="1" md-cols-sm="2" md-cols-md="4" md-cols-gt-md="6" ".
4 Answers
4
This is the simplest Way you can achive that :)
<md-card class="sub-category-grid" style="padding:0px;" (window:resize)="onResize($event)">
<md-grid-list cols="{{test}}" rowHeight="1:1">
<md-grid-tile *ngFor="let item of Items">
{{item.title}}
</md-grid-tile>
</md-grid-list>
</md-card>
// init this var with the default number of columns
test: any = 2;
Items: any = [
{title: "title", img_src: "../../../assets/img/-samples/raketa.png", description: "Description" },
{title: "title", img_src: "../../../assets/img/-samples/raketa.png", description: "Description" },
{title: "title", img_src: "../../../assets/img/-samples/raketa.png", description: "Description" },
{title: "title", img_src: "../../../assets/img/-samples/raketa.png", description: "Description" },
{title: "title", img_src: "../../../assets/img/-samples/raketa.png", description: "Description" },
{title: "title", img_src: "../../../assets/img/-samples/raketa.png", description: "Description" },
{title: "title", img_src: "../../../assets/img/-samples/raketa.png", description: "Description" },
{title: "title", img_src: "../../../assets/img/-samples/raketa.png", description: "Description" },
{title: "title", img_src: "../../../assets/img/-samples/raketa.png", description: "Description" }
]
constructor() { }
ngOnInit() {
}
onResize(event) {
const element = event.target.innerWidth;
console.log(element);
if (element < 950) {
this.test = 2;
}
if (element > 950) {
this.test = 3;
}
if (element < 750) {
this.test = 1;
}
}
Indeed a bit more clean that the other answer. Thanks
– Jimmy Kane
Jul 12 '17 at 10:07
You are welcome bro
– user7956520
Jul 12 '17 at 10:20
You can add directive to your component and then do the work in directive like this;
import { Directive, ElementRef, Input, HostListener, Output } from '@angular/core';
import * as _ from "lodash";
@Directive({ selector: '[myResponsive]' })
export class TestDirective {
@Input() tiles;
@HostListener('window:resize', ['$event'])
onResize(event) {
if (event.target.innerWidth < 980) {
_.each(this.tiles, tile => {
tile.cols = 2;
tile.rows = 1;
});
} else {
this.tiles = [
{text: 'One', cols: 3, rows: 1, color: 'lightblue'},
{text: 'Two', cols: 1, rows: 2, color: 'lightgreen'},
{text: 'Three', cols: 1, rows: 1, color: 'lightpink'},
{text: 'Four', cols: 2, rows: 1, color: '#DDBDF1'}
];
}
}
constructor(el: ElementRef) {
}
}
You also need to add your directive to app.module.ts
import { TestDirective } from "./test.directive";
@NgModule({
imports: [
...
],
declarations: [
TestDirective
]
And your HTML should be like this
<md-grid-list cols="4" rowHeight="100px">
<md-grid-tile myResponsive [(tiles)]="tiles" *ngFor="let tile of tiles"
[colspan]="tile.cols"
[rowspan]="tile.rows"
[style.background]="tile.color">
{{tile.text}}
</md-grid-tile>
</md-grid-list>
How does this adapt to multiple grid lists using the same directive? It seems like you have the default values coded into the directive which may or may not apply to 2nd & 3rd grid lists.
– discodane
May 16 '17 at 13:47
i dont really understand your question but if the other girds separete from each other you can add same directive to each of them. The purpose of the answer is you can use directives to get screen width and use it to change your html. If you are not using css to make it responive. Its just change col and row span dynamically so you can change all the other grids with same directive.
– Onurhan Aytac
May 17 '17 at 7:22
As I understand the responsive part is currently located in flex-layout project. Some of the common utilities from this library will be moved to angular/cdk that material already uses. Flex-layout project provides an observable that you can subscribe to get notifications on break point changes - ObservableMedia. You can also use MediaService service (also from flex-layout) to assert the window sizes.
Therefore this code can be implements like that. Please notes that I use trackBy function to keep the original boxes when toggle happen.
export class AppComponent {
tiles: Array<Object>;
public columns = 4;
private subscription: Subscription;
tilesBig = [
{text: 'One', cols: 3, rows: 1, color: 'lightblue', id: 1},
{text: 'Two', cols: 1, rows: 2, color: 'lightgreen', id: 2},
{text: 'Three', cols: 1, rows: 1, color: 'lightpink', id: 3},
{text: 'Four', cols: 2, rows: 1, color: '#DDBDF1', id: 4},
];
tilesSm = [
{text: 'One', cols: 3, rows: 1, color: 'lightblue', id: 1},
{text: 'Three', cols: 1, rows: 1, color: 'lightpink', id: 3},
{text: 'Four', cols: 2, rows: 1, color: '#DDBDF1', id: 4},
{text: 'Two', cols: 3, rows: 1, color: 'lightgreen', id: 2},
];
constructor(private _media$: ObservableMedia,
private mediaService: MediaService) {
this.subscription = this._media$.subscribe((e: MediaChange) => {
this.toggle();
});
}
ngOnInit() {
this.toggle();
}
private toggle() {
const isSmall = this.mediaService.isActive('lt-md');
this.columns = isSmall ? 3 : 4;
this.tiles = isSmall ? this.tilesSm : this.tilesBig;
}
trackById(index: number, item: any): string { return item['id']; }
}
You can look at code https://stackblitz.com/edit/angular-t325tj?embed=1&file=app/app.component.ts
Making responsive design in angular 4 is not as simple as it is in bootstrape. To make md-grid-list responsive or should change view according to device width then we need to use flex layout library
To have clearity about how reponsive things work in angular visit below links
visit http://brianflove.com/2017/05/03/responsive-angular/
demo http://run.plnkr.co/preview/cja10xr7900083b5wx6srd0r6/
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
This is one of the drawbacks of using a framework that's still in beta. Responsive grid-lists haven't been implemented yet.
– adamdport
May 23 '17 at 14:53