GASで記述したWebアプリ上で画面遷移

仕事じゃなく、さらに維持費とかが考えに無い知人からの
「こういうの欲しい。」
といった相談は、作ったら相手に投げっぱなしでおkな
Google SitesGoogle App Script (GAS)で対応する事が多い。


一応、この2つについて少し紹介すると
GoogleSitesはWYSIWYGでWebページを作れるサービスで、
GASはGoogleDriveのサーバー上で動くjavascriptのこと。
GASはGoogleDrive上でスプレッドシートなんかを処理するのに利用される事もあるけど、今回の話しはGASを使ってGoogleDrive上で動くWebアプリケーションを記述する機能についてのお話。


で、今回はちょっと複雑な入力を処理する事になったので、
GAS内で画面遷移を作る必要があった。

この場合の画面遷移とは、
同一URL内で、(ページ遷移をせずに)UIを切り替える事。

例えば、最初の画面から"次へ"ボタンを押すと
次となる画面が表示されるような形のことだ。

まず、GASにはUiInstanceというUI(ボタンやラベル、テキストボックス)
を保持するルートとなるオブジェクトがあり、全てのUIは
このオブジェクトから生成され、UiInstance自身にaddされることで
表示される画面を構成できる。

こんな感じ

//リクエスト
function doGet() {
    var app = UiApp.createApplication(); //UiInstance作成
    app.add(app.createButton("hoge")); //ボタン追加
    return app; //hogeボタンのある画面が表示される
}


画面をルートから入れ替えるにはUiInstance単位で操作すればいいのでは?
つまり新しくUiInstanceを作成してセットすればいいというのが筋というか、
そういう感じだろう!
と思ってリファレンスを調べていたけど全く手応えが無い。

そしてこの方法ではエラーが発生。

function eventHandler(e) {
    var app = UiApp.getActiveApplication();//既存の画面を取得
    /* ...  */
    var new_app = UiApp.createApplication();//新しい画面を作成
    /* ...  */
    //  ヤバげなerror!
}

現状のGASでは複数のUiInstanceを作成する事が想定されていない様子。


ということで、
画面遷移があるにもかかわらず一つのUiInstanceを使い回すことになると、
画面を移動するたびにUIを全て削除して追加して...
といった冗長なコードを書かないとならなくなる。


海外のフォーラムでもUiInstanceの切り替えができないことについて
相談があったりしたのでそれを読んだ感じ、
画面全体を占めるPanelを作って
それにUIを載せていけばPanel単位で管理出来るよというアイデアがあった。


と言う事で以下に画面遷移のサンプル。

  • 一つの画面に対してPanel自体を生成、破棄して実現
  • 画面の切り替えは一つのPanelを継続して使用する。clear()して新しい画面のUIをそのPanelに改めて構築することで実現

という実装の2パターン。


サンプルコード(GoogleDrive)
サンプルコード(Gist)

サンプル実行


ちなみにUiInstance自身にはclear()が無いのがキモで、
UIをひとまとめに管理するには
なにかしらのコンテナとなるUIが必要ということになっています。
Gridでもいいんだけど今回はそれがPanelだということでした。