gzip Angular files after build

npm i gzipper -g

or locally to devDependencies

npm i gzipper -D

use gzipper with your build commands (e.g. Angular CLI)

"scripts": {
    "build": "ng build && gzipper --verbose ./dist"
  }

compress files to a certain directory ./gzipped

"scripts": {
    "build": "ng build && gzipper --verbose ./dist ./gzipped"
  }

build.bat

ng build --prod --aot && gzipper --verbose ./dist

References
https://www.npmjs.com/package/gzipper

Deploy Angular app to Express

Angular

ng build --prod --aot

app.js in express

var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var compression = require('compression');

var app = express();

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.use(cookieParser());
app.use(compression());
app.use(express.static(path.join(__dirname, 'public'), {maxAge: 31536000}));


app.get('*', function (req, res, next) {
    var file = path.join(__dirname, 'public', 'index.html');
    res.sendFile(file);
});

module.exports = app;

 

Find inner elements using query in Angular Animation

@Component({
  selector: 'inner',
  template: `
    <div [@queryAnimation]="exp">
      <h1>Title</h1>
      <div class="content">
        Blah blah blah
      </div>
    </div>
  `,
  animations: [
   trigger('queryAnimation', [
     transition('* => goAnimate', [
       // hide the inner elements
       query('h1', style({ opacity: 0 })),
       query('.content', style({ opacity: 0 })),

       // animate the inner elements in, one by one
       query('h1', animate(1000, style({ opacity: 1 }))),
       query('.content', animate(1000, style({ opacity: 1 }))),
     ])
   ])
 ]
})
class Cmp {
  exp = '';

  goAnimate() {
    this.exp = 'goAnimate';
  }
}

References
https://angular.io/api/animations/query

Creating reusable animations in Angular

src/app/animations.ts

import {
  animation, trigger, animateChild, group,
  transition, animate, style, query
} from '@angular/animations';

export const transAnimation = animation([
  style({
    height: '{{ height }}',
    opacity: '{{ opacity }}',
    backgroundColor: '{{ backgroundColor }}'
  }),
  animate('{{ time }}')
]);

src/app/open-close.component.ts

import { Component } from '@angular/core';
import { useAnimation, transition, trigger, style, animate } from '@angular/animations';
import { transAnimation } from './animations';

@Component({
    trigger('openClose', [
      transition('open => closed', [
        useAnimation(transAnimation, {
          params: {
            height: 0,
            opacity: 1,
            backgroundColor: 'red',
            time: '1s'
          }
        })
      ])
    ])
  ],
})

References
https://angular.io/guide/reusable-animations

Route transition animations in Angular

src/app/app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { OpenCloseComponent } from './open-close.component';
import { OpenClosePageComponent } from './open-close-page.component';
import { OpenCloseChildComponent } from './open-close.component.4';
import { ToggleAnimationsPageComponent } from './toggle-animations-page.component';
import { StatusSliderComponent } from './status-slider.component';
import { StatusSliderPageComponent } from './status-slider-page.component';
import { HeroListPageComponent } from './hero-list-page.component';
import { HeroListGroupPageComponent } from './hero-list-group-page.component';
import { HeroListGroupsComponent } from './hero-list-groups.component';
import { HeroListEnterLeavePageComponent } from './hero-list-enter-leave-page.component';
import { HeroListEnterLeaveComponent } from './hero-list-enter-leave.component';
import { HeroListAutoCalcPageComponent } from './hero-list-auto-page.component';
import { HeroListAutoComponent } from './hero-list-auto.component';
import { HomeComponent } from './home.component';
import { AboutComponent } from './about.component';
import { InsertRemoveComponent } from './insert-remove.component';


@NgModule({
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    RouterModule.forRoot([
      { path: '', pathMatch: 'full', redirectTo: '/enter-leave' },
      { path: 'open-close', component: OpenClosePageComponent },
      { path: 'status', component: StatusSliderPageComponent },
      { path: 'toggle', component: ToggleAnimationsPageComponent },
      { path: 'heroes', component: HeroListPageComponent, data: {animation: 'FilterPage'} },
      { path: 'hero-groups', component: HeroListGroupPageComponent },
      { path: 'enter-leave', component: HeroListEnterLeavePageComponent },
      { path: 'auto', component: HeroListAutoCalcPageComponent },
      { path: 'home', component: HomeComponent, data: {animation: 'HomePage'} },
      { path: 'about', component: AboutComponent, data: {animation: 'AboutPage'} },

    ])
  ],

src/app/app.component.html

<div [@routeAnimations]="prepareRoute(outlet)" >
  <router-outlet #outlet="outlet"></router-outlet>
</div>

src/app/app.component.ts

prepareRoute(outlet: RouterOutlet) {
  return outlet && outlet.activatedRouteData && outlet.activatedRouteData['animation'];
}

src/app/animations.ts

export const slideInAnimation =
  trigger('routeAnimations', [
    transition('HomePage <=> AboutPage', [
      style({ position: 'relative' }),
      query(':enter, :leave', [
        style({
          position: 'absolute',
          top: 0,
          left: 0,
          width: '100%'
        })
      ]),
      query(':enter', [
        style({ left: '-100%'})
      ]),
      query(':leave', animateChild()),
      group([
        query(':leave', [
          animate('300ms ease-out', style({ left: '100%'}))
        ]),
        query(':enter', [
          animate('300ms ease-out', style({ left: '0%'}))
        ])
      ]),
      query(':enter', animateChild()),
    ]),
    transition('* <=> FilterPage', [
      style({ position: 'relative' }),
      query(':enter, :leave', [
        style({
          position: 'absolute',
          top: 0,
          left: 0,
          width: '100%'
        })
      ]),
      query(':enter', [
        style({ left: '-100%'})
      ]),
      query(':leave', animateChild()),
      group([
        query(':leave', [
          animate('200ms ease-out', style({ left: '100%'}))
        ]),
        query(':enter', [
          animate('300ms ease-out', style({ left: '0%'}))
        ])
      ]),
      query(':enter', animateChild()),
    ])
  ]);

src/app/app.component.ts

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css'],
  animations: [
    slideInAnimation
    // animation triggers go here
  ]
})

fade animation

export const fadeAnimation2 =
  trigger('routeAnimations', [
    transition('* <=> *', [
      style({
        opacity: 0
      }),
      query(':enter, :leave', [
        style({
          opacity: 0
        }),
      ], {optional: true}),
      // Animate the new page in
      query(':enter', [
        animate('200ms ease-in', style({
          opacity: 1
        })),
      ], {optional: true})
    ]),
  ]);

References
https://angular.io/guide/route-animations
https://fireship.io/lessons/angular-router-animations/

Detect window size using Angular

app.component.ts

import {Component, OnInit, HostListener, AfterViewChecked} from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, AfterViewChecked {
  title = 'web-ui';
  screenHeight: any;
  screenWidth: any;

  ngOnInit(): void {

  }

  constructor() {
    this.onResize();
  }

  @HostListener('window:resize', ['$event'])
  onResize(event?) {
    this.getScreenSize();
  }


  /**
   * get size of screen
   */
  getScreenSize() {
    this.screenHeight = window.innerHeight;
    this.screenWidth = window.innerWidth;
    console.log(this.screenHeight, this.screenWidth);
  }

  /**
   * get initial size of appContainer class
   */
  getAppDivSize() {
    this.appHeight = (document.getElementsByClassName('appContainer').item(0) as HTMLElement).offsetHeight;
    this.appWidth = (document.getElementsByClassName('appContainer').item(0) as HTMLElement).offsetWidth;
    console.log(this.appHeight, this.appWidth);
  }
}

 

References
https://stackoverflow.com/questions/45350716/detect-window-size-using-angular-4