やろうとしていること
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
を配置する- データソースは
Inherited: Book
- テーブルに表示する項目は、書籍名、著者、貸し出し日時、借りている人、BookOwner、Location
-
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 を空いているところに配置する
- Text Box → value の右端の逆三角を押して
binding
を選択し、More Options
を選択する- Choose a binding で、
datasource
→query
→filters
→Name
→_contains
の順で選択して OK
- Choose a binding で、
- Text Box → label の右端の逆三角を押して
binding
を選択し、More Options
を選択する- Choose a binding で、
datasource
→model
→fields
→Name
→displayName
の順で選択して OK
- Choose a binding で、
- Text Box → value の右端の逆三角を押して
value にデータソースのフィルタリング条件を設定しています。
やっているのは、 テキストボックスに入力した値が、書籍の名前 (Book.Name) に含まれて (contains) いるレコードを抽出せよ 、という設定です。
_contains
なので部分一致です。_equals
だと完全一致になります。
label で設定したのは、名前の通りでテキストボックスに表示するラベルです。
前回の記事で Book モデルの定義をしましたが、そこで設定した Display Name
を利用します。
所在の絞り込み
- ウィジェット一覧から Dropdown を空いているところに配置する
- Dropdown → label の右端の逆三角を押して
binding
を選択し、More Options
を選択する- Choose a binding で、
datasources
→Location
→model
→fields
→Name
→displayName
の順で選択して OK
- Choose a binding で、
- Dropdown → options は、Choose a binding で、
datasources
→Location
→items
の順で選択して OK - Dropdown → value は、Choose a binding で、
datasource
→query
→filters
→Location
→_equals
の順で選択して OK
- Dropdown → label の右端の逆三角を押して
label は入力欄のラベルです。
options にはドロップダウンで選択できる項目を設定します。既に作成した、所在地を作る画面で作った所在地を表示するようにしています。
value にデータソースのフィルタリング条件を設定しています。
ドロップダウンで選択した値が、書籍の所在地 (Book.Location) と一致 (equals) するレコードを抽出せよ 、という設定です。
なお、options で設定したドロップダウンに表示する値の型と、value で設定する比較対象の型は一致していないとダメです。一致していないと Choose a binding 画面で OK が押せず設定できません。
ここまでで 2 つ条件を設定できるようにしましたが、両方とも入力して検索するとそれぞれの AND 検索になります。
検索ボタン
- ウィジェット一覧から Button を空いているところに配置する
- Button → text を
検索
にする - Button → onClick を
Reload Datasource
にする
- Button → text を
これで検索ボタンを押すと、データソースが再読み込みされるようになります。
条件が入っていれば絞り込まれるし、入ってなければ全件表示されます。
画面同士をつなげる
書籍の一覧画面から、書籍・書籍所有者・所在地の登録画面へ遷移できるようにします。
例えば書籍登録画面への遷移処理は以下の手順で設定します。
- ウィジェット一覧からボタンを配置
- 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 を配置する
- Flow → justify を
center
にする - Flow → alignChildren を
center
にする
- Flow → justify を
- Horizontal Panel 内に、下記を配置する
- 「借りる」ボタン
- 「返す」ボタン
- 「貸出中です」ラベル
- 「借りる」ボタン
- Display → visible を
binding
にして、!@datasource.item.BorrowedBy
とする
- Display → visible を
- 「返す」ボタン
- Display → visible を
binding
にして、@datasource.item.BorrowedBy && @user.email === @datasource.item.BorrowedBy
とする
- Display → visible を
- 「貸出中です」ラベル
- Display → visible を
binding
にして、@datasource.item.BorrowedBy && @user.email !== @datasource.item.BorrowedBy
とする
- Display → visible を
貸し出し履歴を表示
ウィジェット一覧のテーブルを使って貸し出し履歴を表示します。
このテーブルのデータソースはデフォルトで用意される BorrowHistory
でも良いのですが、自作のデータソースも使ってみたいので、書籍ごとに貸し出し履歴を保持するデータソースを作成します。
- 画面左の DATA → BorrowHistory を開き、 DATASOURCES → ADD DATASOURCE を押す
- Name は
BorrowHistoryByBook
として、Query はQuery script
を選択し、Server Script に下記を入力する - + ADD PARAMETER を押下し、
String
を選択する(NewParameter
が新規追加される) -
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/
ここまでで画面の作成は終わりです
画面の作成が一通り終わりました。
次回は各種処理を実行するためのスクリプトを書いていきます。