Angular(ver.8.2) のページを IE11 に対応させたい話
はじめに
この記事は Angular #2 Advent Calendar 2019 一日目の記事です。
以前からちょろちょろ触っていた Angular ですが、そろそろ試しに使ってみたい、ということで、実践を意識して(どうにも逃れられない) IE11 の対応に挑戦してみたいと思います。
Environment
IE11 でページを表示する
デフォルトでは真っ白のページしか表示されないので、まずは表示されるようにしてみます。
といってもやったことは下記に従っただけです。
一応変更した内容を挙げておきます。
- プロジェクトに tsconfig-es5.app.json というファイルを追加
- angular.json で 1.が読み込まれるよう変更
- 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 を使う
Chrome や Firefox などのブラウザでは 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">
- top-page.component.ts に dateText: string を追加してください
- Template Syntax - Angular
おわりに
基本的には自動で良い感じにしてくれる、ということで大変ありがたいのですが、 Angular に任せておきさえすればすべてうまくいく、というわけでもない辺りがちょっと辛いですね。
(主に IE の特に CSS 周りの対応)
まぁあれこれ地雷を踏み抜きながら覚えていくしかないか。。。
個人的には JS Framework 無しから Angular に切り替えて、一番嬉しいのは HTML の部分を TypeScript(JavaScript) ではなく HTML として書ける、ということかなと思っています。
コードで生成しても良いのですが、規模が大きくなってくるとやっぱり分かりづらい。。。
React や Vue だとまた違っていると思うので、そちらも試してみたいなとは思っています。
さて Advent Calender ですが、明日は ringtail003 さんです。
よろしくお願いいたします(..)_