Google App Maker ー Popup の使い方

2017年12月の初めの方に [Popup](https://developers.google.com/appmaker/ui/popups#popups) 系の画面モジュールが追加された。
https://developers.google.com/appmaker/release-notes#popup_dialogs_new_model_events_and_api_updates

これと同じのを自作で実装するとものすごく面倒だった（ので諦めてた）のだが、公式にサポートしてくれるようになったため、リッチなアプリケーションを作りやすくなった。
※ Google 提供の [App Maker templates](https://developers.google.com/appmaker/templates/) なんかは、上記の面倒なやり方で実装されているのでもう参考にしないほうが良い。

本記事では、Popup 系を使うにあたって知っといたほうがいいことをメモがてら記載する。



## Popup の種類
全部で6種類ある。
ぱっと見はぜんぜん違う UI でもベースは一緒なので Popup のテンプレートを選ぶみたいなイメージ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/4f06a872-f5a8-3cc5-1559-e53c9f4ba4e7.png)



## Popup の共通オプション
ポップアップは `PopupOverlay` という Page のようなもので包まれている。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/879d0ad4-d51d-211f-a365-00cd28d99aa8.png)

`PopupOverlay` には共通で定義されているオプションが4つある。
このオプションによって、ユーザの使い勝手が結構変わってくるのでしっかりと抑えておこう。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/f11b23ab-e107-af40-d6e8-85d938873354.png)

### clickOutsideToClose
ポップアップ以外の場所をクリックしたときにポップアップを閉じるか

### navigateToClose
別ページに遷移したときにポップアップを閉じるか

### hasGlass
Page とポップアップの間にオーバーレイ領域を出すか否か

### escapeToClose
Escape キーが押されたときにポップアップを閉じるか



## Empty Popup
空のポップアップ。
自由にポップアップを作りたいときはこれ。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/8072f5d5-02a7-e342-cf7f-052c28153b41.png)



## Navigation menu
（デフォルトでは）画面の左にナビゲーションメニューを出す。
複数ページになるサイトになったら使う感じ。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/df77f3f1-c714-efd6-e487-9e9a2b973a8f.png)



## Confirmation dialog
実行していいかを確認するポップアップ。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/e3d7726a-147e-1197-352d-643e6de7a3c3.png)

### おすすめ実装
Confirmation dialog を何個も作りたくない場合、こんな感じで実装すると良さそう。

※App Maker はボタンの onClick イベントを動的に設定することはできないので、クッションをはさむ形になる。[^1]
[^1]: なんかもっとイケてる方法がある気がする

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/faa87c1f-8231-ec76-15a0-cc69eef7763d.png)


```javascript:ClientScript(ConfirmationDialog)
function ConfirmationDialog(){}
ConfirmationDialog.prototype.confirmRun = function () {
  console.error('function is not allocated.');
};

ConfirmationDialog.prototype.run = function (title, text, runFunction) {
  app.popups.ConfirmationDialog.descendants.ConfirmationTitle.text = title;
  app.popups.ConfirmationDialog.descendants.ConfirmationText.text = text; 
  ConfirmationDialog.prototype.confirmRun = runFunction;
  
  app.popups.ConfirmationDialog.visible = true;
};

ConfirmationDialog.prototype.close = function () {
  app.popups.ConfirmationDialog.visible = false;
};


var confirmationDialog = new ConfirmationDialog();
```

```javascript:ClientScript(Page)
function showConfirmForHoge() {
  confirmationDialog.run(
    'title-hoge',
    'text-hoge',
    function () {
      alert('hogehoge');
      confirmationDialog.close();
    }
  );
}

function showConfirmForPiyo() {
  confirmationDialog.run(
    'title-piyo',
    'text-piyo',
    function () {
      alert('piyopiyo');
      confirmationDialog.close();
    }
  );
}
```

実行するとこんな感じ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/d9d764e3-a08a-4b7e-775e-dbe37b99d827.png)


## Notification dialog
通知のためのポップアップ。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/d7f0e4fe-73ef-6631-30a9-744613ea1e67.png)



## Modal loading indicator
ローディングのスピナーを表示するポップアップ。
オーバーレイで他の操作を無効化出来るのでサーバー通信時はちゃんと使いましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/5739e678-0cc2-be54-9d67-c00555d65b6f.png)


### おすすめ実装
`app.popups.ModalLoadingIndicator.visible`を直接操作しないようにしたほうがソース的にはきれいになるかな。

```javascript:ClientScript
function ModalLoadingIndicator(){}
ModalLoadingIndicator.prototype.show = function (message) {
  app.popups.ModalLoadingIndicator.visible = true;
};
ModalLoadingIndicator.prototype.hide = function (message) {
  app.popups.ModalLoadingIndicator.visible = false;
};

var modalLoadingIndicator = new ModalLoadingIndicator();
```

```javascript:呼ぶ側
modalLoadingIndicator.show();
setTimeout(function() {
  modalLoadingIndicator.hide();
}, 3000);
```

## Snackbar
Google 系のサービスを使っていれば見たことがあると思う。
画面にシュッとバーを出すやつです。
Notification dialog の今風なやつ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/08ba8425-fa5a-e075-1d3d-67a7c56377b0.png)


### おすすめ実装
Snackbar は自動で閉じてくれたほうが嬉しいので次のような実装をしておく。

```javascript:ClientScript
function Snackbar(){}
Snackbar.prototype.open = function (message) {
  app.popups.Snackbar.descendants.SnackbarText.text = message;
  app.popups.Snackbar.visible = true;
  setTimeout(function() {
    app.popups.Snackbar.visible = false;
  }, 3000);
};

var snackbar = new Snackbar();
```

```javascript:呼ぶ側
snackbar.open('hoge');
```