Angular + IE9 + select タグ でプレースホルダー がちゃんと出なかった
Angular 1.2.23 でプルダウン(select)を生成するという簡単なプログラムを書いていた時、IE9で思ったように表示してくれない現象に出会ってしまって大ハマリしたので、メモっておきます・・・。
まず、Angular でHTMLを出力するためにテンプレートの機能を使っていました。そして、以下の様なテンプレートのHTMLを作成しました。ng-options
でリストを生成しています。 value
が空文字の option
タグを用意しておくと1行目にプレースホルダーとしての option
を作成してくれます。便利ですね。
<select ng-model="a" ng-options="x for x in [1,2,3,4,5]">
<option value="">-- Select One --</option>
</select>
これをIE9で実行したところ、なぜか以下の1つ目のプルダウンのようにプレースホルダーが消えてしまっています。(2つ目は問題を解決したあとのコードが表示したものです。どちらもリストの中身はちゃんと出ています)
原因がどこにあるかわからず一つ一つ問題を潰していくと、最終的にテンプレートのHTMLを圧縮したあと生成されるHTMLに問題があることが分かりました。
本来、以下のように生成されて欲しかったHTMLが、
<option value="">-- Select One --</option>
以下のように、value
のあとの =""
が消された状態で出力されていました。
<option value>-- Select One --</option>
今回使用していたgulpのプラグインのgulp-minify-htmlが利用するminimizeというライブラリのオプションを以下のようにすることでこの問題は解決しました。(もともと、以下のオプションの spare
以外は指定していたので、上記の様なアウトプットになっていました。)
minifyHTML({
quotes: true,
empty: true,
spare: true
})
では、なぜ value=""
でないとIE9でちゃんと動作しないかというと、angular.js(1.2.23)の以下の場所で最初に option が空のものを探してそれを emptyOption 変数に代入するという処理をやっています。
|
|
ここで childen[i].value
とやっているところがあります。
これは、DOM の HTMLOptionElement
の value
値を取得しているのですが、IE9では <option value>
となっている場合、value の値ではなく option
タグのテキストの方を取得してくるようになっているようです(今回の例だと – Select One – という文字列)。なので、上記21504行目の処理はスルーされてしまい、せっかく定義したプレースホルダーのoptionが無かったことにされる、というわけでした。
ちなみに、 value
属性がない(空文字でなく、属性そのものがない)場合というのは、上記と同じような仕様(option タグの中のテキストを返す)になるっぽいですね。
https://developer.mozilla.org/ja/docs/Web/API/HTMLOptionElement
テンプレートのHTMLがminifyされて生成されたHTMLをちゃんと意識してないのが大ハマリした原因でした。