AngularJS TIPS
数値(単数/複数)によって表示を切り替えるには?(ng-plurlize)
ng-plurizeディレクティブやngMessageFormatモジュールを使うことで、変数の値によってメッセージ内容を切り替える方法を説明する。
ng-plurizeディレクティブを利用することで、変数の値(単数/複数いずれであるか、3以上である場合、など)によって、表現を切り替えることができます。例えばメールボックスなどのアプリを想定してみましょう。新着メールの件数に応じて、以下のようなメッセージを表示させるものとします。
| 件数 | メッセージ |
|---|---|
| 0 | 新着メッセージはありません。 |
| 1 | ○○さんからのメッセージがあります。 |
| 2 | ○○さん、○○さんからのメッセージがあります。 |
| 3 | ○○さん、○○さんとあと1人からメッセージが届いています。 |
| 4以上 | ○○さん、他●○名からメッセージが届いています。 |
このような表現の差し替えは、以下のようなコードで実現できます。
|
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="UTF-8" />
<title>AngularJS TIPS</title>
</head>
<body ng-controller="MyController">
<div ng-pluralize count="mails.length" offset="2"
when="{
'0': '新着メッセージはありません。',
'1': '{{mails[0].name}}さんからのメッセージがあります。',
'2': '{{mails[0].name}}さん、{{mails[1].name}}さんからのメッセージがあります。',
'one': '{{mails[0].name}}さん、{{mails[1].name}}さんとあと1人からメッセージが届いています。',
'other': '{{mails[0].name}}さん、{{mails[1].name}}さん、他{}名からメッセージが届いています。'
}">
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script>
angular.module('myApp', [])
.controller('MyController', ['$scope', function($scope) {
$scope.mails = [
{ name: '山田太郎', body: 'こんにちは。今年は暑いねー。' },
{ name: '鈴木久美子', body: 'お久しぶりです。元気にしてますか?' },
{ name: '佐藤雄二', body: '今度の日曜日、ランチしに行きませんか。' },
{ name: '山口夕夏', body: 'お誕生日おめでとう!' },
{ name: '田中仁', body: 'いつもお世話になっております。明日はよろしくお願い致します。' }
];
}]);
</script>
</body>
</html>
|

- *1 サンプルを実行する際には、スコープ変数
mailsに含まれる要素の個数を変化させて、メッセージが変化することを確認してください。
ng-plurize属性(ディレクティブ)は、以下の属性とセットで利用します(ただし、offset属性は任意です)。
| 属性 | 概要 |
|---|---|
| count | メッセージ切り替えのための値(件数)を表す変数 |
| when | 件数(count)に応じたメッセージのセット |
| offset | 件数(count)から差し引く値 |
when属性は「件数: メッセージ」のハッシュ形式で表現します。上記のサンプルでは、
count属性の値が0、1、2offset値+1(=one)- それ以上(=
other)
のときのメッセージを、それぞれ定義していることになります。メッセージには、{{...}}の形式で式を埋め込める他、{}で「count - offset」値を反映できます。
エクスプレッションによるメッセージの切り替え
AngularJS 1.4以降では、ngMessageFormatというモジュールが導入され、{{...}}(エクスプレッション)だけでng-plurize属性(ディレクティブ)に相当する表現が可能になりました。以下は、先ほどのリストをngMessageFormatモジュールを使って書き換えたものです。
|
<div>{{mails.length, plural, offset:2
=0 {新着メッセージはありません。}
=1 {{{mails[0].name}}さんからのメッセージがあります。}
=2 {{{mails[0].name}}さん、{{mails[1].name}}さんからのメッセージがあります。}
one {{{mails[0].name}}さん、{{mails[1].name}}さんとあと1人からメッセージが届いています。}
other{{{mails[0].name}}さん、{{mails[1].name}}さん、他#名が[いいね!]と言っています。}
}}</div>
……中略……
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-message-format.min.js"></script>
<script>
angular.module('myApp', [ 'ngMessageFormat' ])
.controller('MyController', ['$scope', function($scope) {
……中略……
}]);
</script>
|
ngMessageFormatモジュールは、AngularJSのコア(angular-messages.min.js)とは別ファイルに含まれています。利用に当たっては、angular-message-format.min.jsをインポートした上で、現在のモジュールからngMessageFormatモジュールへの依存関係を宣言してください。
あとは、エクスプレッションで、以下の形式でメッセージを定義するだけです。
[構文]ngMessageFormatモジュールの構文
{{count, plural, offset: off
 : num { message }
 : ...
}}
- count: 件数を表す式
- off:
count属性から差し引く値 - num: 件数
- message:
num件のときに表示するメッセージ
ほとんどng-plurize属性のそれと対応していますので、特筆すべき点はあまりありません。一点のみ、メッセージの中で件数を埋め込む箇所は、ng-plurize属性では{}を使っていましたが、ngMessageFormatモジュールでは#で表します。
処理対象:モジュール カテゴリ:基本
API:ngPlurlize(ng-plurlize) カテゴリ:ng(コアモジュール) > directive(ディレクティブ)
API:ngMessages カテゴリ:モジュール(Modules)
※以下では、本稿の前後を合わせて5回分(第24回~第28回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。