<!DOCTYPE html>
<html>
<head>
<title>Angular Material Plunker</title>
<link rel="stylesheet" href="assets/style.css" />
<!-- Load common libraries -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/typescript/2.1.6/typescript.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/zone.js/0.7.2/zone.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.47/system.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/web-animations/2.2.2/web-animations.min.js"></script>
<!-- Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script>
System
.import('main.ts')
.catch(console.error.bind(console));
</script>
<!-- Load the Angular Material stylesheet -->
<link href="https://rawgit.com/angular/material2-builds/master/prebuilt-themes/indigo-pink.css" rel="stylesheet">
<style>body { font-family: Roboto, Arial, sans-serif; margin: 0 }</style>
</head>
<body class="mat-app-background">
<material-app>Loading the Angular Material App...</material-app>
</body>
</html>
<!--
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->
import {Component} from '@angular/core';
import {Http} from '@angular/http'
import {bootstrap} from '@angular/platform-browser-dynamic';
import { ResizeService } from './resize.service';
@Component({
selector: 'material-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
private version: any;
sideNameMode = 'over';
showSideNav = false;
enableSideNavToggle = true;
windowWidth = '';
constructor(
http: Http,
private resizeService: ResizeService
) {
// Display the currently used Material 2 version.
this.version = http
.get('https://api.github.com/repos/angular/material2-builds/commits/HEAD')
.map(res => res.json())
}
ngOnInit() {
this.onResize(this.resizeService.currentWindowWidth);
this.resizeService.onResize$.subscribe((window: Window) => {
this.onResize(window.innerWidth);
});
}
onResize(windowWidth: number) {
// console.log('onResize', windowWidth);
this.windowWidth = windowWidth;
if (windowWidth < 1480) {
this.showSideNav = false;
this.sideNameMode = 'over';
this.enableSideNavToggle = true;
} else {
this.showSideNav = true;
this.sideNameMode = 'side';
this.enableSideNavToggle = false;
}
}
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
<md-toolbar color="primary">
Angular Material 2 App
</md-toolbar>
<md-card class="card-demo">
<md-card-subtitle>
Window width: {{windowWidth}}, flex-layout size:
<span fxHide fxHide.xl="false">XL</span>
<span fxHide fxHide.lg="false">LG</span>
<span fxHide fxHide.md="false">MD</span>
<span fxHide fxHide.sm="false">SM</span>
<span fxHide fxHide.xs="false">XS</span>
</md-card-subtitle>
</md-card>
<md-card class="card-demo">
<md-card-subtitle>Responsive content, component in md-tab-group, FORM</md-card-subtitle>
<md-card-content>
<div class="containerX">
<div fxLayout="row" fxLayoutAlign="center" class="coloredContainerX box">
<div
class.xs="fxClass-xs"
class.sm="fxClass-sm"
class.md="fxClass-md"
class.gt-md="fxClass-lg"
>
<md-tab-group fxFlex>
<md-tab label="Super Tab One">
<app-form-content fxFlex></app-form-content>
</md-tab>
<md-tab label="Better Tab Two">
<app-second-tool-content fxFlex></app-second-tool-content>
</md-tab>
</md-tab-group>
</div>
</div>
</div>
</md-card-content>
</md-card>
<md-card class="card-demo">
<md-card-subtitle>Responsive content, content in component, FORM, NO TAB</md-card-subtitle>
<md-card-content>
<div class="containerX">
<div fxLayout="row" fxLayoutAlign="center" class="coloredContainerX box">
<div
class.xs="fxClass-xs"
class.sm="fxClass-sm"
class.md="fxClass-md"
class.gt-md="fxClass-lg"
>
<app-form-content></app-form-content>
</div>
</div>
</div>
</md-card-content>
</md-card>
<md-card class="card-demo">
<md-card-subtitle>Responsive content, component in md-tab-group, NO FORM</md-card-subtitle>
<md-card-content>
<div class="containerX">
<div fxLayout="row" fxLayoutAlign="center" class="coloredContainerX box">
<div
class.xs="fxClass-xs"
class.sm="fxClass-sm"
class.md="fxClass-md"
class.gt-md="fxClass-lg"
>
<md-tab-group fxFlex>
<md-tab label="Super Tab One">
<app-tool-content fxFlex></app-tool-content>
</md-tab>
<md-tab label="Better Tab Two">
<app-second-tool-content fxFlex></app-second-tool-content>
</md-tab>
</md-tab-group>
</div>
</div>
</div>
</md-card-content>
</md-card>
<md-card class="card-demo">
<md-card-subtitle>Responsive content, content in component</md-card-subtitle>
<md-card-content>
<div class="containerX">
<div fxLayout="row" fxLayoutAlign="center" class="coloredContainerX box">
<div
class.xs="fxClass-xs"
class.sm="fxClass-sm"
class.md="fxClass-md"
class.gt-md="fxClass-lg"
>
<app-tool-content fxFlex></app-tool-content>
</div>
</div>
</div>
</md-card-content>
</md-card>
<md-card class="card-demo" >
<md-card-title>Responsive Flex Directives</md-card-title>
<md-card-subtitle>Use the show hide APIs to responsively show or hide elements:</md-card-subtitle>
<md-card-content>
<div class="containerX">
<div fxLayout="row" class="coloredContainerX box" >
<div fxFlex.gt-sm="67" fxFlex="33"> flex 33% on mobile, <br>and 66% on gt-sm devices. </div>
<div fxFlex.gt-sm="33" fxFlex="67"> flex 67% on mobile, <br>and 33% on gt-sm devices. </div>
</div>
</div>
</md-card-content>
<!--<md-card-footer style="width:95%">-->
<!--<media-query-status></media-query-status>-->
<!--</md-card-footer>-->
</md-card>
/** Add Transpiler for Typescript */
System.config({
transpiler: 'typescript',
typescriptOptions: {
emitDecoratorMetadata: true
},
packages: {
'.': {
defaultExtension: 'ts'
},
'vendor': {
defaultExtension: 'js'
}
}
});
System.config({
map: {
'main': 'main.js',
// Angular specific mappings.
'@angular/core': 'https://unpkg.com/@angular/core/bundles/core.umd.js',
'@angular/common': 'https://unpkg.com/@angular/common/bundles/common.umd.js',
'@angular/compiler': 'https://unpkg.com/@angular/compiler/bundles/compiler.umd.js',
'@angular/animations': "https://unpkg.com/@angular/animations/bundles/animations.umd.js",
'@angular/animations/browser': 'https://unpkg.com/@angular/animations/bundles/animations-browser.umd.js',
'@angular/http': 'https://unpkg.com/@angular/http/bundles/http.umd.js',
'@angular/forms': 'https://unpkg.com/@angular/forms/bundles/forms.umd.js',
'@angular/router': 'https://unpkg.com/@angular/router/bundles/router.umd.js',
'@angular/platform-browser': 'https://unpkg.com/@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser/animations': 'https://unpkg.com/@angular/platform-browser/bundles/platform-browser-animations.umd.js',
'@angular/platform-browser-dynamic': 'https://unpkg.com/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/material': 'https://rawgit.com/angular/material2-builds/master/bundles/material.umd.js',
'@angular/flex-layout' : 'https://rawgit.com/angular/flex-layout-builds/master/bundles/flex-layout.umd.js',
// Rxjs mapping
'rxjs': 'https://unpkg.com/rxjs',
},
packages: {
// Thirdparty barrels.
'rxjs': { main: 'index' },
}
});
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {BrowserModule} from '@angular/platform-browser';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {NgModule} from '@angular/core';
import { FormsModule } from '@angular/forms';
import {CommonModule} from '@angular/common';
import {HttpModule} from '@angular/http';
import {AppComponent} from './app.component';
import {MaterialModule} from '@angular/material';
import { FlexLayoutModule } from '@angular/flex-layout';
import {ToolContentComponent} from './tool-content.component';
import {FormContentComponent} from './form-content.component';
import {SecondToolContentComponent} from './second-tool-content.component';
import {ResizeService} from './resize.service';
@NgModule({
imports: [
BrowserModule,
FormsModule,
CommonModule,
HttpModule,
MaterialModule,
BrowserAnimationsModule,
FlexLayoutModule
],
declarations: [
AppComponent,
ToolContentComponent,
SecondToolContentComponent,
FormContentComponent
],
bootstrap: [AppComponent],
providers: [
ResizeService
]
})
export class PlunkerAppModule {}
platformBrowserDynamic().bootstrapModule(PlunkerAppModule);
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
#Angular Material2 with Flex-Layout
## Bug description
When scaling down from a larger window to a smaller one, the Material2 select control breaks the layout.
Example:
- start page at 1360px, shrink it to below 960px (the layout changes from row to column, the controls go beyond the green box).
- going even smaller, below 600px, same effect (here, the contents should shrink dynamically to fill the available screen width inside the green box).
Strange effect:
- set the window width to very small (300px), then RELOAD the plunkr preview window (not the browser)
- it still looks off a bit, but when increasing the window size now to around 310px, it looks like it's supposed to look
- from this state, increasing the window to SM, MD, LG, XL and then back again to something above 310px does not break the layout anymore!
.containerX {
border: solid 1px #b6b6b6;
}
.colorNested, .colored, .coloredContainerX {
min-height:200px;
}
md-card {
background-color: white;
}
div.coloredContainerX > div, div.colorNested > div > div {
padding: 8px;
box-shadow: 0px 2px 5px 0 rgba(52, 47, 51, 0.63);
opacity: 0.9;
color: #fff;
/*text-align: center;*/
}
div.coloredContainerX > div:nth-child(1), div.colorNested > div > div:nth-child(1) {
background-color: #009688;
}
div.coloredContainerX > div:nth-child(2), div.colorNested > div > div:nth-child(2) {
background-color: #3949ab;
}
div.coloredContainerX > div:nth-child(3), div.coloredChildren > div:nth-child(3), div.colorNested > div > div:nth-child(3) {
background-color: #9c27b0;
}
div.coloredContainerX > div:nth-child(4), div.coloredChildren > div:nth-child(4), div.colorNested > div > div:nth-child(4) {
background-color: #b08752;
}
div.coloredContainerX > div:nth-child(5), div.coloredChildren > div:nth-child(5), div.colorNested > div > div:nth-child(5) {
background-color: #5ca6b0;
}
div.colored > div {
padding: 8px;
box-shadow: 0px 2px 5px 0 rgba(52, 47, 51, 0.63);
opacity: 0.9;
color: #fff;
text-align: center;
}
div.colored > div:nth-child(1), .one {
background-color: #009688;
}
div.colored > div:nth-child(2), .two {
background-color: #3949ab;
}
div.colored > div:nth-child(3), .three {
background-color: #9c27b0;
}
div.colored > div:nth-child(4), .four {
background-color: #8bc34a;
}
div.colored > div:nth-child(5), .five {
background-color: #03A9F4;
}
div.colored > div:nth-child(6), .six {
background-color: #c9954e;
}
div.colored > div:nth-child(7), .seven {
background-color: #FF5722;
}
.hint {
margin:5px;
font-size:0.9em;
color: #a3a3a3;
margin-bottom:0;
}
.title {
margin:5px;
font-size:0.9em;
color: #5c5c5c;
}
.box {
border: solid 1px gray;
}
button.md-primary {
margin-left:25px;
}
.demo-content {
background-color: ghostwhite;
}
md-toolbar-row button {
min-width: 150px;
}
div.colored.box.nopad > div {
padding: 0;
}
.intro {
margin-top: -52px;
margin-left: 15px;
color: #5c5c5c;
}
.version {
font-size:0.8em;
color: #aeaeae;
margin-top:20px;
}
.blocks {
min-width: 75px;
min-height: 50px;
}
html, body {
height:100%;
min-height:100vh;
}
<div fxFlex fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="16px">
<div fxFlex fxFlex.gt-sm="40" class="box-one">
app-form-sample
</div>
<div fxFlex fxFlex.gt-sm="60" class="box-two">
div 2 <br>
div 2 <br>
div 2 <br>
</div>
</div>
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-tool-content',
templateUrl: './tool-content.component.html',
styles: [`
.box-one {
background-color: #5ca6b0;
}
.box-two {
background-color: palegreen;
}
.box-three {
background-color: sandybrown;
}
`]
})
export class ToolContentComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
.card-demo md-card,
.card-demo md-card-content {
margin-bottom: 24px;
}
.card-demo md-card-footer {
left: 24px;
margin-bottom: 24px;
}
.containerX {
border: solid 1px #b6b6b6;
box-sizing: content-box !important;
}
.hint {
color: #a3a3a3;
font-size:0.9em;
margin:5px;
margin-bottom:0;
}
.forceAbove {
margin-top: -275px;
}
.large {
height:200px;
}
.large div.one, .large div.two {
color:white;
}
div {
box-sizing: border-box;
}
.small-demo {
min-height: 128px;
padding-bottom: 40px;
display: block;
background-color: #eee;
}
.colorNested, .colored, .coloredContainerX {
min-height:200px;
}
.taller {
height:300px;
}
md-card {
background-color: white;
}
div.coloredContainerX > div, div.colorNested > div > div {
padding: 8px;
box-shadow: 0px 2px 5px 0 rgba(52, 47, 51, 0.63);
opacity: 0.9;
color: #fff;
}
div.coloredContainerX > div:nth-child(1), div.colorNested > div > div:nth-child(1), div.box1 {
background-color: #009688;
}
div.coloredContainerX > div:nth-child(2), div.colorNested > div > div:nth-child(2), div.box2 {
background-color: #3949ab;
}
div.coloredContainerX > div:nth-child(3), div.coloredChildren > div:nth-child(3), div.colorNested > div > div:nth-child(3), div.box3 {
background-color: #9c27b0;
}
div.coloredContainerX > div:nth-child(4), div.coloredChildren > div:nth-child(4), div.colorNested > div > div:nth-child(4) {
background-color: #b08752;
}
div.coloredContainerX > div:nth-child(5), div.coloredChildren > div:nth-child(5), div.colorNested > div > div:nth-child(5) {
background-color: #5ca6b0;
}
div.colored > div {
padding: 8px;
box-shadow: 0px 2px 5px 0 rgba(52, 47, 51, 0.63);
opacity: 0.9;
color: #fff;
text-align: center;
}
div.colored > div:nth-child(1), .one {
background-color: #009688;
}
div.colored > div:nth-child(2), .two {
background-color: #3949ab;
}
div.colored > div:nth-child(3), .three {
background-color: #9c27b0;
}
div.colored > div:nth-child(4), .four {
background-color: #8bc34a;
}
div.colored > div:nth-child(5), .five {
background-color: #03A9F4;
}
div.colored > div:nth-child(6), .six {
background-color: #c9954e;
}
div.colored > div:nth-child(7), .seven {
background-color: #FF5722;
}
.hint {
margin:5px;
font-size:0.9em;
color: #a3a3a3;
margin-bottom:0;
}
.title {
margin:5px;
font-size:0.9em;
color: #5c5c5c;
}
.box {
border: solid 1px gray;
}
button.md-primary {
margin-left:25px;
}
.demo-content {
background-color: ghostwhite;
}
md-toolbar-row button {
min-width: 150px;
}
div.colored.box.nopad > div {
padding: 0;
}
.intro {
margin-top: -52px;
margin-left: 15px;
color: #5c5c5c;
}
.blocks {
min-width: 75px;
min-height: 50px;
border-radius: 3px;
}
.black {
border-radius: 5px;
min-width: 75px;
min-height: 50px;
color: white;
background-color: #292929;
padding: 8px;
box-shadow: 0px 2px 5px 0 rgba(52, 47, 51, 0.63);
text-align: center;
}
.target {
background-color: #05ffb0;
color: #310736;
cursor: pointer;
}
.two_h {
min-height : 100px;
}
.two_w {
min-width: 125px;
}
.four_h {
min-height: 75px;
}
.four_w {
min-width: 100px;
}
.bigger {
padding: 0 20px;
padding-bottom: 30px;
}
md-toolbar .md-toolbar-layout md-toolbar-row {
flex-direction: column;
align-content: flex-start;
align-items: flex-start;
min-height: 40px;
}
.demo-content .small-demo:first-child {
margin-top: 40px;
}
md-card-content pre {
font-size: 12px;
white-space: pre-wrap;
}
.fixed { height:275px; }
.hint { margin:5px; font-size:0.9em;color: #a3a3a3; }
md-radio-group { padding-top: 15px;}
.demo_controls { width: 100%;height: 200px; margin-bottom: 25px; }
.demo_controls > div { padding-top: 15px; color: #6c6c6c; }
.demo { margin-bottom:60px; }
.fxClass-xs {
width: 100%;
}
.fxClass-sm {
width: 360px;
}
.fxClass-md {
width: 760px;
}
.fxClass-lg {
width: 1160px;
}
.fxClass-xl {
}
.box-one {
background-color: #5ca6b0;
}
.box-two {
background-color: palegreen;
}
.box-three {
background-color: sandybrown;
}
<div fxFlex fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="16px">
<div fxFlex fxFlex.gt-sm="20" class="box-one">
div 1 <br>
div 1 <br>
</div>
<div fxFlex fxFlex.gt-sm="40" class="box-two">
div 2 <br>
div 2 <br>
div 2 <br>
</div>
<div fxFlex fxFlex.gt-sm="40" class="box-three">
div 4 <br>
div 4 <br>
</div>
</div>
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-second-tool-content',
templateUrl: './second-tool-content.component.html',
styles: [`
.box-one {
background-color: darksalmon;
}
.box-two {
background-color: cornflowerblue;
}
.box-three {
background-color: coral;
}
`]
})
export class SecondToolContentComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
.md-select-container {
display: inline-block;
margin-top: 2px;
min-height: 57px;
}
.example-full-width {
width: 100%;
}
.md-select-container-first {
margin-top: 12px;
}
.md-full-width {
width: 100%;
}
md-button-toggle-group {
height: 40px;
}
.result-right {
text-align: right;
}
.macro-percentages {
color: darkgray;
/*font-size: smaller;*/
}
.box-one {
background-color: #5ca6b0;
}
.box-two {
background-color: palegreen;
}
.box-three {
background-color: sandybrown;
}
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-form-content',
templateUrl: './form-content.component.html',
styleUrls: ['./form-content.component.css']
})
export class FormContentComponent implements OnInit {
weight: string;
selectedValue: string;
selectedDrink: string;
foods = [
{value: 'steak-0', viewValue: 'Steak'},
{value: 'pizza-1', viewValue: 'Pizza'},
{value: 'tacos-2', viewValue: 'Tacos'}
];
drinks = [
{value: 'coke-0', viewValue: 'Coke'},
{value: 'beer-1', viewValue: 'Beer'},
{value: 'wine-2', viewValue: 'Wine'}
];
constructor() { }
ngOnInit() {
}
onSubmit(value, event) {
console.log('submit');
}
}
<div fxFlex fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="16px">
<div fxFlex fxFlex.gt-sm="40" class="box-one">
<form #form="ngForm" (ngSubmit)="onSubmit(form.value, $event)" novalidate>
<div>
<md-input-container class="example-full-width">
<input #weightInputElement mdInput [(ngModel)]="weight" name="weight" placeholder="Weight" required>
</md-input-container>
</div>
<div >
<!--<md-select placeholder="Favorite food" style="display:block" [(ngModel)]="selectedValue" name="food">-->
<md-select class="example-full-width" placeholder="Favorite food" [(ngModel)]="selectedValue" name="food">
<md-option *ngFor="let food of foods" [value]="food.value">
{{food.viewValue}}
</md-option>
</md-select>
</div>
<br>
<br>
<!--
<div >
<md-select placeholder="Favorite drink" style="display:block" [(ngModel)]="selectedDrink" name="drink">
<md-option *ngFor="let drink of drinks" [value]="drink.value">
{{drink.viewValue}}
</md-option>
</md-select>
</div>
-->
</form>
</div>
<div fxFlex fxFlex.gt-sm="60" class="box-two">
div 2 <br>
div 2 <br>
div 2 <br>
</div>
</div>
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { EventManager } from '@angular/platform-browser';
@Injectable()
export class ResizeService {
// http://stackoverflow.com/a/43833815/54159
get currentWindowWidth(): number {
return window.innerWidth;
}
get onResize$(): Observable<Window> {
return this.resizeSubject.asObservable();
}
private resizeSubject: ReplaySubject<Window>;
constructor(private eventManager: EventManager) {
this.resizeSubject = new ReplaySubject();
this.eventManager.addGlobalEventListener('window', 'resize', this.onResize.bind(this));
}
private onResize(event: UIEvent) {
this.resizeSubject.next(<Window>event.target);
}
}