みなさんこんにちは!GASおじさんです。
「GAS x HTMLで確認画面付きの本格的な発注フォームを作ろう」シリーズの第10回です。
前回の記事はこちら。
今回はフォームのバリデーションを実装していきます。
Youtubeでも解説していますので、動画で見たい方は以下からどうぞ。
現状のフォームの問題点
前回までの記事で作ったフォームには以下のような問題点があります。
- 商品が0個でも送信できてしまう
- 入力途中で商品が在庫切れとなっても送信できてしまう
商品が0個でも送信できてしまう
このように商品の個数がすべて0個の状態で「確認画面へ」を押すと…
このように確認画面に遷移し、そのまま発注できてしまいます。
しかし、最低でも1個は注文してもらうようにしたいので、商品数が0個の場合は、「少なくとも1個位以上注文してください。」のようなアラートを出した上で、再入力を促したいですね。
入力途中で商品が在庫切れとなっても送信できてしまう
このフォームは複数のユーザーから同時に入力されることも想定しています。
自分が入力しているときに、他の誰かが発注して、商品が在庫切れとなってしまうこともありえるでしょう。
そういったケースを再現するために、スプレッドシート側で「水」の在庫数を5個にしてみます。
次に、フォーム画面で「水」を10個にして「確認画面へ」ボタンを押してみます。
この場合、「入力中に在庫切れとなりました」のようなアラートを出して、再入力を促したいですが、現状ではそのまま確認画面に進めてしまいます。
このまま「発注する」ボタンを押すと発注できてしまいますが、在庫数がないのに発注されるのは困りますね。
バリデーションを実装
上記の問題を解決するために、バリデーションを実装していきましょう。
商品個数が0個で送信されてしまったときの対策
コード.gsのdoPost
関数を以下のように書き換えてください。
function doPost(e) {
const items = getAllRecords('商品');
// 注文数が0の場合、alert付きでindex.htmlを返す
if(isZero(e, items)) {
const template = HtmlService.createTemplateFromFile('index');
const alert = '少なくとも1個以上注文してください。';
template.deployURL = ScriptApp.getService().getUrl();
template.formHTML = getFormHTML(e, items, alert);
const htmlOutput = template.evaluate();
return htmlOutput;
}
// index.htmlで「確認画面へ」ボタンが押されたらconfirm.htmlへ
if(e.parameter.confirm) {
const template = HtmlService.createTemplateFromFile('confirm');
template.deployURL = ScriptApp.getService().getUrl();
template.confirmHTML = getConfirmHTML(e, items);
const htmlOutput = template.evaluate();
return htmlOutput;
}
// confirm.htmlで「修正する」ボタンが押されたらindex.htmlへ
if(e.parameter.modify) {
const template = HtmlService.createTemplateFromFile('index');
template.deployURL = ScriptApp.getService().getUrl();
template.formHTML = getFormHTML(e, items);
const htmlOutput = template.evaluate();
return htmlOutput;
}
// confirm.htmlで「発注する」ボタンが押されたらcomplete.htmlへ
if(e.parameter.submit) {
createOrder(e, items);
updateZaiko(e, items);
sendMail(e, items);
const template = HtmlService.createTemplateFromFile('complete');
template.deployURL = ScriptApp.getService().getUrl();
const htmlOutput = template.evaluate();
return htmlOutput;
}
}
4〜12行目を追加しました。
5行目でisZero
という未定義の関数を呼び出しているので、これを定義する必要があります。以下のコードをコピーしてコード.gsに貼り付けてください。
function isZero(e, items) {
let total = 0;
for(const item of items) {
const itemId = item['商品ID'];
const count = Number(e.parameter[itemId]);
if(count) total += count;
}
if(total == 0) return true;
return false;
}
これで実装完了です。デプロイして確認してみます。
商品をすべて0個の状態で「確認画面へ」を押すと…
再度フォーム入力画面に遷移し、赤い文字で「少なくとも1個以上注文してください。」と表示されました!
商品が在庫切れになってしまったときの対策
コード.gsのdoPost
関数を以下のように書き換えてください。
function doPost(e) {
const items = getAllRecords('商品');
// 注文数が0の場合、alert付きでindex.htmlを返す
if(isZero(e, items)) {
const template = HtmlService.createTemplateFromFile('index');
const alert = '少なくとも1個以上注文してください。';
template.deployURL = ScriptApp.getService().getUrl();
template.formHTML = getFormHTML(e, items, alert);
const htmlOutput = template.evaluate();
return htmlOutput;
}
// 商品が在庫切れの場合、alert付きでindex.htmlを返す
if(outOfStock(e, items)) {
const template = HtmlService.createTemplateFromFile('index');
const alert = '入力中に在庫切れとなりました。再度入力してください。';
template.deployURL = ScriptApp.getService().getUrl();
template.formHTML = getFormHTML(e, items, alert);
const htmlOutput = template.evaluate();
return htmlOutput;
}
// index.htmlで「確認画面へ」ボタンが押されたらconfirm.htmlへ
if(e.parameter.confirm) {
const template = HtmlService.createTemplateFromFile('confirm');
template.deployURL = ScriptApp.getService().getUrl();
template.confirmHTML = getConfirmHTML(e, items);
const htmlOutput = template.evaluate();
return htmlOutput;
}
// confirm.htmlで「修正する」ボタンが押されたらindex.htmlへ
if(e.parameter.modify) {
const template = HtmlService.createTemplateFromFile('index');
template.deployURL = ScriptApp.getService().getUrl();
template.formHTML = getFormHTML(e, items);
const htmlOutput = template.evaluate();
return htmlOutput;
}
// confirm.htmlで「発注する」ボタンが押されたらcomplete.htmlへ
if(e.parameter.submit) {
createOrder(e, items);
updateZaiko(e, items);
sendMail(e, items);
const template = HtmlService.createTemplateFromFile('complete');
template.deployURL = ScriptApp.getService().getUrl();
const htmlOutput = template.evaluate();
return htmlOutput;
}
}
14〜22行目を追加しました。
15行目でoutOfStock
という未定義の関数を呼び出しているので、これを定義する必要があります。以下のコードをコピーしてコード.gsに貼り付けてください。
function outOfStock(e, items) {
for(const item of items) {
const itemId = item['商品ID'];
const zaiko = item['在庫数'];
const count = Number(e.parameter[itemId]);
if(zaiko < count) {
return true;
}
}
return false;
}
これで実装完了です。再度デプロイして確認してみます。
スプレッドシート側で水の在庫数を5個にして、
フォーム画面で水を10個注文しようとすると…
再度フォーム入力画面に遷移し、赤い文字で「入力中に在庫切れとなりました。再度入力してください。」と表示されました!
まとめ
以上、バリデーションを実装しました。
ユーザー体験を極限まで高めるために、裏側の細かいところまで気を配って実装することが大切ですね。
引き続きユーザー体験を高めるために、次回はスマホ対応させていきましょう!
連載目次: GAS x HTMLで確認画面付きの本格的な発注フォームを作ろう
- 【GAS x HTML】確認画面付きの本格的な発注フォームを作る
- GASとHTMLで簡単なWebページを表示する方法
- 【GAS】Bootstrapを使ってフォーム画面を作る方法
- doPost関数で確認画面ページに遷移させよう
- 確認画面ページから発注完了ページに遷移させよう
- 【GASxHTML】スプレッドシートの商品データを動的に表示する
- フォームの入力内容を確認画面ページに渡そう
- 確認画面ページに「修正する」ボタンを実装しよう
- 確認画面ページの「発注する」ボタンクリック後の機能を実装しよう
- 【GASxHTML】フォームのバリデーションを実装しよう
- GASとHTMLで作ったWebアプリをスマホ対応させる方法
コメント