【SAPUI5】モデルについて整理（i18n, JSON, OData)

##はじめに
モデル、バインドについていくつかの記事で触れてきたので、そのまとめ編という位置づけです。**i18nもJSONもODataも、名前は違えどモデルなので扱いは同じ**です。今回は、モデルを扱う上で押さえておくとよいと思ったことをまとめます。

関連記事：
[【SAPUI5】MVCを完成させよう](https://qiita.com/tami/items/b398f0849fb2bd178d0a)
[【SAPUI5】SAPUI5のMVCをレストランに例えると](https://qiita.com/tami/items/952c4e290349643949ec)

##モデルの種類
3つの分類方法でモデルの種類について説明します。
###①データの形式による分類

| モデルの種類      | 用途              |
|:-----------------|:------------------|
| Resource(i18n)モデル|多言語対応のために使う|
| JSONモデル          |クライアント側で持つ比較的小さなデータ |
| ODataモデル         |バックエンド側で持つデータ |

###②データのスコープによる分類
モデルにはアプリケーション全体で使えるモデルと、ビューに固有のモデルがあります。ResourceモデルとODataモデルはアプリケーション全体で使うことができます。JSONモデルにはアプリケーション全体で使えるものと、ビューに固有のものがあります。
ビューに固有のJSONデータはローカル変数のような役割で、たとえばODataを読み書きする際にデータを編集するために使用したりします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/9aa56b70-2368-f6a6-480e-79f9b45113dd.png)

###③デフォルトモデルとそれ以外（名無しのモデルと名前ありモデル）
デフォルトモデルとは「名無し」のモデルで、以下のようにモデル名を指定せずに直接アクセスすることができます。デフォルトモデルは1つのアプリケーションに1つだけ持つことができます。

```xml
<List items="{/OrderSet}">
```
デフォルトモデル以外の場合は、以下のようにモデル名 + >を先頭に指定します。

```xml
<List items="{mPrice>/product}">
```
i18nモデルの場合も同様です。（i18nモデルはデフォルトモデルではないので、先頭にi18nがつく）

```xml
<ObjectAttribute title="{i18n>priceTitle}"/>
```


##モデルの作り方
モデルはインスタンス化してから使います。アプリケーション全体で使うモデルの場合、manifest.jsonファイルでモデルを定義することで、自動的にインスタンス化されます。
manifest.jsonの書き方については以下の記事に記載しています。

- i18nモデル
[【SAPUI5】i18nで多言語対応](https://qiita.com/tami/items/139e312b1ec047814411)

- JSONモデル
[【SAPUI5】MVCを完成させよう](https://qiita.com/tami/items/b398f0849fb2bd178d0a)

- ODataモデル
[【SAPUI5】OData(8) ODataを使ったSAPUI5アプリケーションの作り方 開発編-1](https://qiita.com/tami/items/3990f98f5cb10818be52)
[【SAPUI5】OData(9) ODataを使ったSAPUI5アプリケーションの作り方 開発編-2](https://qiita.com/tami/items/bdbd8774ea9527ea6790)

###ビュー固有のモデルの作り方
ビューに対応するコントローラの中でモデルを登録します。
WebIDEでテンプレートからアプリケーションを作ったときにコントローラに自動的にinitメソッドが登録されるので、これを参考にするのがよいと思います。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/3636518b-bffe-ff6a-c70f-bd79f9c63c2b.png)


デフォルトで登録されたinitメソッドです。JSONモデルを作って、名前をつけてビューにセットしています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/3ebdb4cf-6e6f-b966-3ba1-df54b0cdd3b8.png)

以下のように要素を追加することができます。

```javascript
			var oViewModel = new JSONModel({
				busy: false,
				delay: 0,
				lineItemListTitle: this.getResourceBundle().getText("detailLineItemTableHeading"),
				order: {
					"OrderId": "",
					"OrderNo": "100",
					"OrderDate": "",
					"CustomerName": "Mob58-002",
					"TotalAmount": "0",
					"Currency": "USD",
					"NavOrderItems": []
				}
			});
```
##Binding typeについて
モデルのデータをビューの項目にひもづけることをバインドと呼びます。i18nもJSONもODataも同じ方法でバインドすることができます。バインドには以下のタイプがあります。

- Property binding
コントロールのプロパティにモデルのデータを直接設定すること

- Element binding
コントロールにモデルを丸ごとバインドすること。そのコントロールおよびその子のコントロールは相対パスでモデルのデータを参照することができる

- Aggregation binding
複数行のデータを持つモデルをリストに割り当てること。明細行が自動的に作られる

バインドの種類については以下のページで解説しています。
[【SAPUI5】Aggregation bindingで複数アイテムを表示](https://qiita.com/tami/items/e90cb3ca18280c829995)

###絶対パスと相対パス
絶対パスとは対象のデータをフルパスで指定することです。相対パスとはアクセスしたい要素名だけ指定することです。絶対パスの場合は先頭にスラッシュがつき、相対パスの場合はつきません。
以下のようなモデルがある場合、

```json
{ 
    "product" : {
        "name" : "pumpkin",
        "price": 150
    }
}
```
コントロールが親子の関係になっているとき、親の要素に絶対パスでバインドすれば子の要素は相対パスでモデルにアクセスできます。

```xml
<List items="{/products}"> →絶対パス
    <items>
         <ObjectListItem
             title="{name}" →相対パス
             number="{price}">
         </ObjectListItem>
     </items>
</List>   
```

##Binding modeについて
Binding typeと似ていますが、こちらはデータの更新に関するモードです。
以下の3つがあります。

| Binding mode     | 説明              |
|:-----------------|:------------------|
| One-way|データの読み込みのみでアプリケーション側から更新はできない|
| Two-way|データの読み書きが可能 |
| One-time|1回だけモデルのデータが読み込まれる|

モデルの種類ごとにデフォルトのBindingモードが決まっています。i18nは固定値のようなものなのでOne-time, その他は(OData V2を除き）Two-wayとなっています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/d26ef60a-23d9-ce8f-3a20-5047415f8b41.png)
https://sapui5.hana.ondemand.com/#/topic/68b9644a253741e8a4b9e4279a35c247 より引用

Binding modeはモデルのインスタンス化の際に上書き可能です。（以下を参照）
https://sapui5.hana.ondemand.com/#/topic/1a08f70951a744b1a7962b09665cc92f

##よくある失敗
絶対パスでの指定の際、先頭のスラッシュを忘れるとデータが表示されません。あれ？と思ったらバインドが正しくできているか確認してみましょう。特に名前ありモデルだと見落としやすいです。
NG

```xml
<List items="{mPricelist>products}">
```
OK

```xml
<List items="{mPricelist>/products}">
```