Angular
Flex
Layout

Sophisticated component layout engine for

Angular

Ekaterina Orlova
github.com/cheerypick
Frontend web dev /Accenture Norway
Co-organizer of Mobile Era Oslo
Angular trainer @ Netology Russia
@cheerypick

Flexbox CSS
+

mediaQuery
 

Browser support

Why

@angular/flex-layout?

Pure TypeScript layout engine

Independent of Angular Material

...but they work fine together

No external CSS stylesheets

Angular CLI Integration

 

Static API

 

Responsive API

npm install --save @angular/flex-layout@latest
import { FlexLayoutModule }
    from '@angular/flex-layout';
...
@NgModule({
  imports: [FlexLayoutModule],
  ...
})
export class AppModule { }

Import Angular Flex-Layout NgModule

Install Angular Flex-Layout

v2.0.0-beta.8

Static Layout API

CSS Flexbox Model

API for DOM containers

fxLayout
 
fxLayoutWrap
 
fxLayoutGap
 
fxLayoutAlign
 

<div fxLayout="row" 
    fxLayout.xs="column"> </div>

<div fxLayoutWrap> </div>

<div fxLayoutGap="10px"> </div>

<div fxLayoutAlign="start stretch">
</div>

fxLayout API

<div fxLayout="row">
  <div>One</div> 
  <div>Two</div> 
  <div>Three</div> 
  <div>Four</div>
</div>
<div fxLayout="column">
  <div>One</div> 
  <div>Two</div> 
  <div>Three</div> 
  <div>Four</div>
</div>

fxLayout options

<div fxLayout="row-reverse"> 
...
</div>
Value Equivalent CSS
default {flex-direction: row}
row {flex-direction: row}
row-reverse {flex-direction: row-reverse}
column {flex-direction: column}
column-reverse {flex-direction: column-reverse}

API for flex elements

fxFlex

fxFlexOrder
 
fxFlexOffset
 
fxFlexAlign
 
fxFlexFill
 

<div fxFlex="1 2 
calc(15em + 20px)"></div>


<div fxFlexOrder="2"></div>

<div fxFlexOffset="20px"></div>


<div fxFlexAlign="center"></div>


<div fxFlexFill></div>

fxFlex API

  1. flex-grow

  2. flex-shrink

  3. flex-basis

3 parameters:

flex-grow

Defines how much a flexbox item should grow  ( proportional to the others) if there's space available.

flex-shrink

defines how much a flexbox item should shrink if there is not enough space available.

flex-basis

controls the default size of the element

fxFlex

<div fxLayout="row" fxLayoutAlign="center">
  <div fxFlex="1 1 auto">One</div>
  <div fxFlex="5 1 auto">Two</div>
  <div fxFlex="1 1 auto">Three</div>
  <div fxFlex="1 1 auto">Four</div>
</div>

fxFlex options

  • fxFlex
  • fxFlex="2 2 calc(10em + 10px)"
  • fxFlex="102px"
  • fxFlex="auto"

The flex-basis values can be pixels, percentages, calcs, em, vw, vh, or known aliases.

alias Equivalent CSS
grow {flex: 1 1 100%}
initial {flex: 0 1 auto}
auto {flex: <grow> <shrink> 100%}
none {flex: 0 0 auto}
nogrow {flex: 0 1 auto}
noshrink {flex: 1 0 auto}

Runtime expressions

To use runtime expressions, developers should use the box-notation to specify 1-way DataBind (to an expression).

<div [fxFlex]="twoColumnSpan">...</div>

Responsive API

Material Design Breakpoints

Media Queries and Aliases

breakpoint mediaQuery
xs 'screen and (max-width: 599px)'
sm 'screen and (min-width: 600px) and (max-width: 959px)'
md 'screen and (min-width: 960px) and (max-width: 1279px)'
lg 'screen and (min-width: 1280px) and (max-width: 1919px)'
xl 'screen and (min-width: 1920px) and (max-width: 5000px)'
lt-sm 'screen and (max-width: 599px)'
lt-md 'screen and (max-width: 959px)'
lt-lg 'screen and (max-width: 1279px)'
lt-xl 'screen and (max-width: 1919px)'
gt-xs 'screen and (min-width: 600px)'
gt-sm 'screen and (min-width: 960px)'
gt-md 'screen and (min-width: 1280px)'
gt-lg 'screen and (min-width: 1920px)'

Visibility example

<div fxShow fxHide.xs="false" fxHide.lg="true"></div>
  • xl, then fallback to the default fxShow; so the div is shown
  • lg, then the div is hidden (since the value === 'true')
  • md, then fallback to the default fxShow; so the div is shown
  • sm, then fallback to the default fxShow; so the div is shown
  • xs, then the div is shown (since the value === 'false')

Sizing example

<div fxFlex="50%" fxFlex.gt-sm="100%"></div>
  • xl, then fallback to 'gt-sm' so the div sizing is 100%
  • lg, then fallback to 'gt-sm' so the div sizing is 100%
  • md, then fallback to 'gt-sm' so the div sizing is 100%
  • sm, then fallback to the default fxFlex="50%"; so the div is 50%
  • xs, then fallback to the default fxFlex="50%"; so the div is 50%

Special Responsive Features

fxShow
 
fxHide
 
ngClass
 
ngStyle
 

<div fxShow 
    [fxShow.xs]="isVisibleOnMobile()"></div>

<div fxHide 
    [fxHide.gt-sm]="isVisibleOnDesktop()"></div>


<div 
    [ngClass.sm]="{'fxClass-sm': hasStyle}"></div>

<div 
    [ngStyle.xs]="{color: 'blue'}"></div>


ngClass API

@angular/flex-layout ngClass directive is a subclass of the @angular/common ngClass directive

Classname assignments with               selector (and its responsive versions) are destructive and will overwrite any existing classnames in use.

class
<div class="default" class.xs="responsive"></div>

This div has either default or responsive class assigned!

ngClass API

The Flex-Layout ngClass adds responsive features to add/remove CSS classes  for activated breakpoints

<some-element ngClass="first second" 
  [ngClass.xs]="{'first':false, 'third':true}"> 
</some-element>

for xs:

  • remove the class='first'
  • keep the class='second'
  • add the class='third'

Adaptive layouts

  • different components for different breakpoints
  • alter animations based on viewport size

JavaScript API (Imperative)

Programmatic features

ObservableMedia
 
BREAKPOINTS
 
BaseFxDirectiveAdapter
 

constructor(public 
    media:ObservableMedia ) {}

providers: [{provide: BREAKPOINTS,
    useValue: MY_CUSTOM_BREAKPOINTS }]


export class ClassDirective
    extends NgClass {}

ObservableMedia

injectable ObservableMedia service provides mediaQuery activations notifications for all registered breakpoints

ObservableMedia:

API summary

  • subscribe(): Subscription
  • asObservable(): Observable<MediaChange>
  • isActive(query: string): boolean

 

ObservableMedia::subscribe()

subscribe(
  next?: (value: MediaChange) => void,
  error?: (error: any) => void,
  complete?: () => void
): Subscription;

Subscribe to mediaQuery activations

import {Subscription} from "rxjs/Subscription";
import {MediaChange, ObservableMedia}
  from "@angular/flex-layout";

constructor(media: ObservableMedia) {
  this.watcher = media.subscribe(
    (change: MediaChange) => {

      if ( change.mqAlias == 'xs') {
        this.loadMobileContent();
      }

    });
}

ObservableMedia::asObservable()

 

import {Subscription} from "rxjs/Subscription";
import 'rxjs/add/operator/filter';
import {MediaChange, ObservableMedia} 
from "@angular/flex-layout";


export class MyDemo {

  constructor(media: ObservableMedia) {
      media.asObservable()
        .filter((change: MediaChange) => 
            change.mqAlias == 'xs')
        .subscribe(() => this.loadMobileContent() );
  }
}

ObservableMedia::isActive()

 

import {MediaChange, ObservableMedia} 
from "@angular/flex-layout";

const PRINT_MOBILE = 'print and (max-width: 600px)';

@Component({
   selector : 'responsive-component',
   template: `
      <div class="ad-content" *ngIf="media.isActive('xs')">
        Only shown if on mobile viewport sizes
      </div>
   `
})
export class MyDemo implements OnInit {
  constructor(public media: ObservableMedia) { }

  ngOnInit() {
    if (this.media.isActive('xs') && !this.media.isActive(PRINT_MOBILE)) {
       this.loadMobileContent();
    }
  }
}

Custom breakpoints

  • Developers can easily override the default breakpoints used within Flex-Layout

  • Build custom providers to override the default BreakPointRegistry provider

     

 

 

Customising breakpoints

import { NgModule } from '@angular/core';
import { DEFAULT_BREAKPOINTS, BreakPoint } from '@angular/flex-layout'
import { validateSuffixes } from '@angular/flex-layout/utils';

/**
 * For mobile and tablet, reset ranges
 */
function updateBreakpoints((it:BreakPoint) => {
  switch(it.alias) {
    case 'xs' : it.mediaQuery =  '(max-width: 470px)';   break;
    case 'sm' : it.mediaQuery =  '(min-width: 471px) and (max-width: 820px)'; break;
  }
  return it;
})

@NgModule({
  providers: [
    // register a Custom BREAKPOINT Provider
    {
      provide : BREAKPOINTS,
      useFactory : function customizeBreakPoints() {
        return validateSuffixes(RAW_DEFAULTS.map( updateBreakpoints ));
      }
    }
  ]
})
export class MyBreakPointsModule { }

"Holy Grail" of layouts

<div>
  <header>header</header>
  <div>

    <nav>nav</nav>

    <article>article</article>

    <aside>aside</aside>

  </div>
  <footer>footer</footer>
</div>
<div fxLayout="column">
  <header>header</header>
  <div fxLayout="row" fxFlex>

    <nav fxFlex="1 6 20%">nav</nav>

    <article fxFlex="3 1 60%">article</article>

    <aside fxFlex="1 6 20%">aside</aside>

  </div>
  <footer>footer</footer>
</div>
<div fxLayout="column">
  <header>header</header>
  <div fxLayout="row" fxLayout.xs="column" 
    fxFlex="1 1 auto">

    <nav fxFlex="1 6 20%" fxFlexOrder 
        fxFlexOrder.xs="2">nav</nav>

    <article fxFlex="3 1 60%" fxFlexOrder 
        fxFlexOrder.xs="1">article</article>

    <aside fxFlex="1 6 20%" fxFlexOrder 
        fxFlexOrder.xs="3">aside</aside>

  </div>
  <footer>footer</footer>
</div>

Resources

Angular Flex-Layout

https://github.com/angular/flex-layout

Visual guide to Flex

http://cssreference.io/flexbox/

Slides

http://slides.com/cherrypick/deck-9

Demo

https://github.com/cheerypick/flex-app

Gitter Chat

https://gitter.im/angular/flex-layout

Quiz time!

Join at kahoot.it

with Game PIN:

121761

Thank you!

Ekaterina Orlova

@cheerypick

github.com/

twitter.com/

Made with Slides.com