vaguely

和歌山に戻りました。ふらふらと色々なものに手を出す毎日。

Angular(ver.8.2) のページを IE11 に対応させたい話

はじめに

この記事は Angular #2 Advent Calendar 2019 一日目の記事です。

以前からちょろちょろ触っていた Angular ですが、そろそろ試しに使ってみたい、ということで、実践を意識して(どうにも逃れられない) IE11 の対応に挑戦してみたいと思います。

Environment

  • npm : ver.6.13.1
  • Angular : ver.8.2.14
  • Angular-cli : ver.8.3.19
  • VSCode : ver.1.41.0-insider

IE11 でページを表示する

デフォルトでは真っ白のページしか表示されないので、まずは表示されるようにしてみます。

といってもやったことは下記に従っただけです。

一応変更した内容を挙げておきます。

  1. プロジェクトに tsconfig-es5.app.json というファイルを追加
  2. angular.json で 1.が読み込まれるよう変更
  3. ng serve --configuration es5 で実行( package.json の Scripts に追加しても良い)

2.について、サンプルを丸コピーしたらプロジェクトが見つからないとエラーになりました。

angular.json

"serve": {
  "builder": "@angular-devkit/build-angular:dev-server",
  "options": {
      ...
  },
  "configurations": {
    "production": {
     ...
    },
    "es5": {
      "browserTarget": "app:build:es5" ← ここでエラー。 app をプロジェクト名にする必要がある。
    }
  }
},

Grid layout を有効にする

Angular には 以前 PostCSS で利用していた Autoprefixer が組み込まれており、 Flexbox などは IE でもそのまま使用できます。

ただ、 Grid Layout は対応されていない(多分)ため、個別に対応が必要です。

PostCSS の場合は postcss.config.js に書いていたわけですが、 Angular の場合は CSS に下記を追加します。

/* autoprefixer grid: autoplace */ 
#grid-frame{
    height: 30%;
    width: 90%;
    display: grid;
    grid-template-columns: 10% 10%;
    grid-template-rows: 15% 85%;
}
...

これで IE11 でも Grid Layout が有効になります。

ただし、この状態だと grid-column と grid-row が聞かず、 要素を横に grid-template-columns の数だけ並べ、超過すると改行、という動作となります。

autoplace の部分を変更すれば良さげですが。。。

背景色に Alpha のある色を設定する

まぁ Angular 独自の話ではないのですが。。。

000000AA のように、 background-color で RGBA で色指定をしてしまうと、 IE では色が表示されません。

rgba(r, g, b, a) を使って指定する必要があります。

#frame-background{
  background-color: rgba(17, 17, 17, 0.67);
}

PostCSS を使っていたときは自動で変換してくれていたので、つい見逃していました orz

Pikaday を使う

ChromeFirefox などのブラウザでは input type="date" とすれば Date Picker が使えるわけですが、 IE ではそうはいかない、ということで、以前使用した Pikaday を使えるようにしたいと思います。

本当は Angular 用に用意された Date Picker もあるようなので、そちらにした方が便利なのかもしれませんが、仕事でも既に Pikaday を使っているため、まずはそちらを試してみます。

Install

npm install --save moment pikaday @types/pikaday

正直なところ、基本的な使い方はほぼ一緒です。

CSS(pikaday.css) は各画面共通ということで styles.css でインポートすることにしました。

styles.css

@import '../node_modules/pikaday/css/pikaday.css';

あとは Pikaday に関連付けるだけです。

今回は top-page というコンポーネントで使うことにしました。

top-page.component.ts

import { Component, OnInit } from '@angular/core';
import * as Pikaday from 'pikaday';

~省略~

export class TopPageComponent implements OnInit {

~省略~

  ngOnInit() {
    let picker = new Pikaday({ 
      field: document.getElementById('datepicker') 
    });
  }
}

top-page.component.html

<input type="text" id="datepicker">

Data bindings

さて、せっかくの Angular なので、値の受け取りは Two-way data binding を使いたいところ。

が、何も考えずに [(ngModel)]="dateText" のように書いてしまうと、 Pikaday で値が入力された場合にイベントが発火せず、 dateText の中身は空のままです。

この原因は上記で設定されているイベントが (input) であるためで、これを (change) にしてやる必要があります。

top-page.component.html

<input type="text" id="datepicker"
  [value]="dateText" (change)="dateText=$event.target.value">

おわりに

基本的には自動で良い感じにしてくれる、ということで大変ありがたいのですが、 Angular に任せておきさえすればすべてうまくいく、というわけでもない辺りがちょっと辛いですね。
(主に IE の特に CSS 周りの対応)

まぁあれこれ地雷を踏み抜きながら覚えていくしかないか。。。

個人的には JS Framework 無しから Angular に切り替えて、一番嬉しいのは HTML の部分を TypeScript(JavaScript) ではなく HTML として書ける、ということかなと思っています。

コードで生成しても良いのですが、規模が大きくなってくるとやっぱり分かりづらい。。。

React や Vue だとまた違っていると思うので、そちらも試してみたいなとは思っています。

さて Advent Calender ですが、明日は ringtail003 さんです。

よろしくお願いいたします(..)_