やろうとしていること
Google App Maker を使って、社内用の書籍管理アプリを作っています。
前回やったこと
前回はアプリで使用する予定のモデルを作成しました。
今回やること
画面を作っていきます。
ページフラグメントを作成する
ページを作る前に、各ページに埋め込む共通部品(ページフラグメント)を作っておきます。
ヘッダーを作成
各画面の上部に表示させます。
サービス名とログインユーザーのメールアドレスを表示するだけのシンプルなものにします。
ページフラグメントを作成
画面左側の PAGES → + を押し、次に Page Fragment を選択 → CREATE します。
作成すると PageFragment という名前で画面左側の PAGES 下に出てくるので、名前を Header に変えます。
PageFragment → ⁝ → Rename から名前変更します。
ヘッダーのかたちにする
ここからヘッダーの形を作っていきます。
初期表示されている Panel を幅が 600、高さが 75 くらいの横長なサイズに変えます。
幅、高さは Panel を選択して、画面右側の Property Editor 内の Main → dimensions 内から変更できます。
ヘッダーの色などのスタイルは、このパネル内に配置する子パネル側で設定したいと思うので、このパネルは透明にしておきます。
画面左上で Regular が選択されている箇所(スタイル)を Transparent にします。
透明になりました。
部品を配置するためのパネルを作成
次に子パネルを配置します。
画面左上の 
 を押して、ウィジェットの一覧を表示します。
この中から Layout → Horizontal Panel をドラッグアンドドロップで、パネル内に置きます。
今置いた子パネルを選択した状態で、Property Editor から下記の設定をします。
- Panel → name を 
HeaderContainerに変更(任意) - Layout → Left, Top を 
0に変更 - Layout → Width の 
pxをautoに変更(→するとオプションが増える) - Layout → Right を 
0に変更 - Layout → Height を 外側のパネルの高さより少し小さいか同じに変更
 - Flow → alignChildren を 
centerに変更 
子パネルを親パネルにぴったり揃えています。
スタイルを Regular から Primary に変更します。青くなりました。
こんな感じになっていると思います。
幅を auto にしたのは、表示するブラウザの幅によって横に伸縮してほしいためです。
また Horizontal Panel を配置したのは、ヘッダー内に表示する文字が固定位置ではなく、左寄せ/右寄せされるようにするためです。
ヘッダー内の文字などを作成
次にヘッダー内に文字を表示します。
ウィジェットの一覧から、サービス名とメールアドレス用に Label を2つと、Horizontal Panel を1つを HeaderContainer 内に配置します。
配置する順番は左から Label, Horizontal Panel, Label の順です。
- 左の Label
- ダブルクリックし、
書籍管理に変える - スタイルを 
Titleに変える - Spacing → Margin Left を 
16に変える 
 - ダブルクリックし、
 - Horizontal Panel
- スタイルを 
Transparentに変える - Layout → Horizontal → Size を 
fill parentに変える(ヘッダーの範囲内で目一杯広がる) 
 - スタイルを 
 - 右の Label
- Label → text の右端の逆三角を押し、
bindingを選択する - 続けて出てくる Choose a binding で以下の順で選択して OK
datasources- 
CurrentUser(前回決めたデータソース名) - 
item(itemsではない) PrimaryEmail
 - Spacing → Margin Right を 
16に変える 
 - Label → text の右端の逆三角を押し、
 
バインディングとは
バインディングとは、あるデータソース内のフィールドと画面の部品(or その他)とを紐付けること だと理解しています。
バインディングされていると、データソース内の値が変われば、バインディング先の画面部品に表示されている値も変わります。逆も同じです(双方向)。
なお、↑でやった PrimaryEmail の後に #readonly と追記すると、データソース→画面の単方向だけにできるようです。
ここまでで以下のようになっていると思います。
「処理中...」を作成
データ読み込み中などによく出てくる、くるくる回るあれを作ります。
何か処理中の時に表示し、処理が終わったら消えるようにする予定です。
部品を配置するためのパネルを作成
新たにページフラグメントを作り、名前を Loading にします。
このページフラグメントは画面端に小さく出れば良いと思うので、初期表示されたパネルも小さくしておきます。幅:150、高さ:70 くらいで。
ヘッダーと同じく、パネルの色を透明にします。
続いて部品配置用のパネルを配置します。
部品は横に並べたいので Horizontal Panel を今あるパネル内にピッタリ配置して色を変えます。
下記の手順でやります。
- パネル内に Horizontal Panel を配置する
 - (今置いたパネルの)Layout → Left, Top を 
0にする - (今置いたパネルの)Layout → Width, Height を 
autoにする - (今置いたパネルの)Layout → Right, Bottom を 
0にする - (今置いたパネルの)スタイルを 
Darkにする 
これで最初からあったパネルの中に、Horizontal Panel がある状態になりました。
くるくる回る部分を作成
- ウィジェット一覧から 
SpinnerとLabelを配置する - 配置する位置を中央にするため、Horizontal Panel を選択し、Flow → justifyとalignChildren を 
centerにする - 配置した Label をダブルクリックして、
Loading...にする(何でも良いです) 
ここで画面右上の ! に数字が付きます。

「何か問題があるよ」と教えてくれていて、開くと問題が確認できてその箇所に飛べます。
問題の箇所に飛ぶと、さっき配置した Spinner の Display → visible がフォーカスされます。
visible には @datasource.loading..... と設定されています。 データソースが読み込み中(または...)の時に表示する という意味です。しかしスピナーのデータソースは現在 None です。従い、スピナーにデータソースを設定すれば問題は解決します。
が、そもそもこのフラグメントは何か処理中の時に表示し、処理が終わったら消える、という想定なので、スピナー自体はずっと表示されていれば良いです。
ということで、visible の逆三角から value を選択し、出てきたチェックボックスをチェック(true)します。
これで datasource を使わなくなったため、問題が消えました。
ページを作成する
いよいよ、ここからページを作ります。
書籍の登録画面を作成
画面左側の PAGES → + を押し、次に Page を選択 → NEXT します。
Page name は書籍の登録画面なので、 BookCreate としました。
Page datasource には、このページで主に使用するデータソースを設定します。Book を選択して CREATE します。
ヘッダーを配置
前に作成したヘッダーをページに配置します。
ウィジェット一覧の Your Page Fragments に出てきます。
- 配置したらページ上部に横いっぱいに広げます。
 
- ヘッダーの Layout → Left, Top を 
0にする - ヘッダーの Layout → Width を 
autoにする - ヘッダーの Layout → Right を 
0にする 
入力フォームを作る
ウィジェット一覧の Form をページ内に配置します。
- Choose datasource は 
Inherited: Bookで良いです(ページのデータソースと同じになる) - Choose form type は作る画面は登録画面なので 
Insertにします - Choose form fields は入力フォームに出すフィールドです。書籍名、著者、URL、BookOwner、Location を選択しました
 
「処理中...」を配置
ウィジェット一覧のヘッダーと同じところにあります。
- 下記のようにして、画面の左下に出るようにします。
 
- Layout の 1 つめの 
MOREを押して Right, Bottom を表示する - Layout → Left は 
20、Top はautoにする(20は適当です) - Layout → Bottom を 
20にする 
- 続いて、処理中の時だけ表示されるように設定します。
 
- Display → visible の逆三角から 
bindingを選択し、More Optionsを選択する - Choose binding の下部に 
@datasource.loading || @datasource.creating || @datasource.deletingと設定する 
登録画面なので @datasource.creating だけでも良いと思います。
書籍所有者の登録画面を作成
「書籍の登録」画面と同様の手順でページを作り、ヘッダーと入力フォーム、処理中を配置します。
データソースは BookOwner にします。
所在地の登録画面を作成
同じ手順で作成します。
データソースは Location にします。
書籍の一覧画面を作成
書籍の一覧画面は、このサービスのメイン画面です。
登録されている書籍の一覧をテーブルで表示して、行を選択したらその書籍の詳細が表示されるようなものにする想定です。
- ページのデータソースを 
Bookにして、ページを新規作成する - ウィジェット一覧から 
Tableを配置する
3. データソースはInherited: Book
4. テーブルに表示する項目は、書籍名、著者、貸し出し日時、借りている人、BookOwner、Location
5.More optionsのDeletable rowsのチェックを外す 
一度アプリを起動してみる
画面右上の PREVIEW を押すとアプリが起動します。
初回起動時はおなじみの認証画面が表示されます。
プレビュー中の画面では、画面左上のドロップダウンからページを切り替えられます。
今作った書籍の一覧画面(一覧は空っぽ)が表示されれば OK です。
書籍登録画面で書籍を登録すれば、書籍の一覧に現れるようになります。
日付欄に時刻まで表示する
日付は標準だと yyyy-MM-dd 形式で表示されます。
時刻も表示されるように変更します。
- テーブル内の貸し出し日時の明細行のラベル(
BorrowedAt)を選択 - Label → text → More Options
 - 既に入力されている 
@datasource.item.BorrowedAtに続けて、#formatDate('yyyy-MM-dd HH:mm:ss')と入力 
#formatDate はバインディングトランスフォーマーという機能を利用しています。
日付のフォーマット以外にも用意されています。
https://developers.google.com/appmaker/scripting/api/transformers
検索機能を追加
一覧に表示する書籍を、書籍名と所在で絞り込めるようにします。
書籍名の絞り込み
- ウィジェット一覧から TextBox を空いているところに配置する
2. Text Box → value の右端の逆三角を押してbindingを選択し、More Optionsを選択する
3. Choose a binding で、datasource→query→filters→Name→_containsの順で選択して OK
9. Text Box → label の右端の逆三角を押してbindingを選択し、More Optionsを選択する
10. Choose a binding で、datasource→model→fields→Name→displayNameの順で選択して OK 
value にデータソースのフィルタリング条件を設定しています。
やっているのは、 テキストボックスに入力した値が、書籍の名前 (Book.Name) に含まれて (contains) いるレコードを抽出せよ 、という設定です。
_contains なので部分一致です。_equals だと完全一致になります。
label で設定したのは、名前の通りでテキストボックスに表示するラベルです。
前回の記事で Book モデルの定義をしましたが、そこで設定した Display Name を利用します。
所在の絞り込み
- ウィジェット一覧から Dropdown を空いているところに配置する
2. Dropdown → label の右端の逆三角を押してbindingを選択し、More Optionsを選択する
3. Choose a binding で、datasources→Location→model→fields→Name→displayNameの順で選択して OK
3. Dropdown → options は、Choose a binding で、datasources→Location→itemsの順で選択して OK
4. Dropdown → value は、Choose a binding で、datasource→query→filters→Location→_equalsの順で選択して OK 
label は入力欄のラベルです。
options にはドロップダウンで選択できる項目を設定します。既に作成した、所在地を作る画面で作った所在地を表示するようにしています。
value にデータソースのフィルタリング条件を設定しています。
ドロップダウンで選択した値が、書籍の所在地 (Book.Location) と一致 (equals) するレコードを抽出せよ 、という設定です。
なお、options で設定したドロップダウンに表示する値の型と、value で設定する比較対象の型は一致していないとダメです。一致していないと Choose a binding 画面で OK が押せず設定できません。
ここまでで 2 つ条件を設定できるようにしましたが、両方とも入力して検索するとそれぞれの AND 検索になります。
検索ボタン
- ウィジェット一覧から Button を空いているところに配置する
 - Button → text を 
検索にする - Button → onClick を 
Reload Datasourceにする 
これで検索ボタンを押すと、データソースが再読み込みされるようになります。
条件が入っていれば絞り込まれるし、入ってなければ全件表示されます。
画面同士をつなげる
書籍の一覧画面から、書籍・書籍所有者・所在地の登録画面へ遷移できるようにします。
例えば書籍登録画面への遷移処理は以下の手順で設定します。
- ウィジェット一覧からボタンを配置
 - Button → onClick で 
Navigate to Page...→BookCreateを選択 - ボタン名をわかりやすいものに変更
 
書籍一覧画面からそれぞれに遷移できるようになったら、それぞれの画面から書籍一覧画面に戻るボタンも作成します。
書籍の詳細画面を作成
書籍の一覧から、行を選択した時にポップアップで開く画面です。
ここで「借りる」「返す」といった操作や、これまでの貸し出し履歴を見れるようにします。
- ページの新規作成で 
Popupを選択し、Empty popupを作成する - Main → name は、
BookDetail - Main → hasGlass をチェックする
 - Main → escapeToClose をチェック外す
 
ポップアップ部分を選択して、
- Popup → datasource を 
Bookにする - ポップアップ部分を適当に大きくする
 
書籍名を表示
ポップアップ内に書籍名を表示します。
- ウィジェット一覧から Label を配置する
 - Label → text を 
bindingにし、ドロップダウンからNameを選ぶ - スタイルを変更する(文字を大きく表示する)
 
リンクを表示
書籍が持っている URL を画面から利用できるようにします。
- ウィジェット一覧から Link を配置する
 - Link → text を任意の文字列にする
 - Link → href を 
bindingにし、ドロップダウンからUrlを選ぶ - Link → target を 
_blankにする(任意) - Display → visible を 
bindingにし、!!@datasource.item.Urlにする 
画面にリンクを表示し設定されている URL に飛べるようにしました。
URL 未設定だとリンクは表示されません。
借りる、返すボタンを作成
書籍の貸し借り状況に応じて、
- 借りる
 - 返す
 - 貸出中です
 
の表示をします。一度に表示されるのは上記のどれか1つとなる想定です。
- ウィジェット一覧から Horizontal Panel を配置する
2. Flow → justify をcenterにする
3. Flow → alignChildren をcenterにする - Horizontal Panel 内に、下記を配置する
5. 「借りる」ボタン
6. 「返す」ボタン
7. 「貸出中です」ラベル - 「借りる」ボタン
9. Display → visible をbindingにして、!@datasource.item.BorrowedByとする - 「返す」ボタン
11. Display → visible をbindingにして、@datasource.item.BorrowedBy && @user.email === @datasource.item.BorrowedByとする - 「貸出中です」ラベル
13. Display → visible をbindingにして、@datasource.item.BorrowedBy && @user.email !== @datasource.item.BorrowedByとする 
貸し出し履歴を表示
ウィジェット一覧のテーブルを使って貸し出し履歴を表示します。
このテーブルのデータソースはデフォルトで用意される BorrowHistory でも良いのですが、自作のデータソースも使ってみたいので、書籍ごとに貸し出し履歴を保持するデータソースを作成します。
- 画面左の DATA → BorrowHistory を開き、 DATASOURCES → ADD DATASOURCE を押す
 - Name は 
BorrowHistoryByBookとして、Query はQuery scriptを選択し、Server Script に下記を入力する - 
- ADD PARAMETER を押下し、
Stringを選択する(NewParameterが新規追加される) 
 - ADD PARAMETER を押下し、
 - 
NewParameterをBookKeyに変更する - Sorting に 
BorrowedAtを選択し、Ascendingのチェックを外す(降順になる) 
var bookKey = query.parameters.BookKey;
if (bookKey) {
  query.filters.Book._key._equals = bookKey;
}
return query.run();
Server Script に設定したのは、このデータソースのデータを取得するスクリプトです。
書籍ごとの貸し出し履歴を取得します。
追加した BookKey パラメーターは書籍のキーです。このデータソースを利用する前に設定しておくことで、特定の書籍に紐付いている貸し出し履歴のみを取得します。
データソースができたら貸し出し履歴のテーブルを作ります。
- ウィジェット一覧からテーブルを配置する
 - データソースは 
BorrowHistoryByBookにする - 表示するフィールドは任意、
Editableのチェックを外す - 
Deletable rowsのチェックも外す 
閉じるボタンを作成
このポップアップを閉じるためのボタンを作ります。
ボタンにはアイコンを表示してみます。
- ウィジェット一覧からボタンを配置する
 - Button → text を 
closeにする - スタイルを 
Iconにする( × に変わる) - Button → onClick を、 
Hide Popup...→BookDetailにする 
スタイルを Icon にすることで、アイコン表示に切り替わります。
アイコンは他にもあります。
https://material.io/resources/icons/
ここまでで画面の作成は終わりです
画面の作成が一通り終わりました。
次回は各種処理を実行するためのスクリプトを書いていきます。
参考サイト










