開発情報・ナレッジ

投稿者:SPIRERS ナレッジ向上チーム 2022年3月31日 (木)

Web申請アプリ サイト設計・構築

SPIRAL ver.2はプログラミング経験がなくても、オリジナルの業務アプリの制作・カスタマイズできるローコード開発プラットフォームです。
詳しくは SPIRAL ver.2 とはをご覧ください。

SPIRAL ver.2を初めて操作する際に何をどう設定すればいいのか?どう管理すればいいのか?と迷う方も多いのではないでしょうか。そこで活用シーンが多い業務アプリの作成手順を通して、
アプリ(DB・メール)設計・構築 / サイト設計・構築 / ユーザ・アプリロール・グループ設定
に各工程を分け、ポイントやおすすめ機能・強化ガジェットを紹介いたします。

第一弾は「Web申請アプリ」です。
この記事は サイト設計・構築 のフェーズとなります。
関連記事はこちら

変更・改定履歴

  • 追加

    Web申請フォームデモへのリンクを追加

サイト機能

SPIRAL ver.2 のサイト管理機能では、静的なWebページを作成したり、
データベースに対して登録・更新するフォーム や データベースの情報を一覧形式で表示させるページなどを作成できます。
詳細は、サイト機能の全体像を確認してください。
今回は、サイト機能を使って、「Web申請ページ」と「再申請ページ」を作成します。

フロー・使用機能の整理

申請者が行う操作は、下記の 2つです。
申請処理
▼申請処理で使用する機能
ページ機能 Web申請ページ
ページ機能 利用規約ページ
ブロック機能 登録フォーム
ブロック機能 フリーコンテンツ
※ 利用規約の文章を設定するブロックです。
【完成イメージ】
差し戻された場合の再申請処理
▼再申請の処理で使用する機能
認証エリア 再申請ページ表示用の認証機能
※ メール本文中にある専用リンクからアクセス可能なクリックログイン認証を使用します。
ページ機能 再申請ページ
※ 認証エリア発行時に自動生成されます。
ブロック機能 更新フォーム
※ 事務局からの差戻しメールは、アプリ(DB・メール)設計・構築 にて設定します。
【完成イメージ】
各機能の詳細に関しては、下記を参照ください。
ページ機能
ブロック機能
認証エリア

Web申請ページ作成

手順1:Web申請用ページ・利用規約ページ作成
サイト内に公開するページの作成を行います。
識別名がURLのディレクトリ名になるので、使用したいURLの階層に合わせて設定してください。
設定方法は、「ビジュアル設定」で設定します。
手順2:登録ブロック作成
Web申請ページの設定画面のブロック設定から「+」ボタンから新規登録ブロックを作成します。
登録フォームもビジュアル設定でデザインは自由に変更していただいて、問題ありません。

▼フィールド一覧
フィールド 使用状況
申請番号 入力項目 ※ 自動発番の強化ガジェットにて使用
氏名 入力項目
会社名 入力項目
郵便番号 入力項目
都道府県 入力項目
市区町村・番地 入力項目
ビル名・部屋番号等 入力項目
電話番号 入力項目
メールアドレス 入力項目
業種 入力項目
業種_その他 入力項目
書類ファイル 入力項目
同意 入力項目
ステータス(事務局担当者) 使用しない ※ 管理項目のため
ステータス(事務局長) 使用しない ※ 管理項目のため
ステータス(申請者-再申請) 使用しない ※ 管理項目のため
ステータス(共通) 使用しない ※ 管理項目のため
【申請者向け】
事務局担当者コメント入力
使用しない ※ 管理項目のため
【事務局長向け】
事務局担当者コメント入力
使用しない ※ 管理項目のため
【事務局担当者向け】
事務局長コメント入力
使用しない ※ 管理項目のため
手順3:利用規約用フリーコンテンツの作成
サイト内に公開するページの作成を行います。
利用規約の設定画面のブロック設定から「+」ボタンから新規登録ブロックを作成します。
ビジュアル設定にて、利用規約の記載を行います。
手順4:動作確認
ページの作成が完了しましたら、テスト環境にて動作確認を行います。
テスト環境は、ver.2 にログインしているユーザのみ閲覧可能となっておりますのでご注意ください。
詳細は、テスト環境/本番環境とリリースで確認してください。
デザイン崩れなく、申請できれば、作成完了となります。
ポイント①
見出しをリッチにするための CSS を追加しています。

CSS
form .sp-form-html:first-child {
    margin-bottom: 40px !important;
    margin: auto;
}
form .sp-form-html:first-child p {
    border-bottom: solid 3px #D91438;
    position: relative;
    color: #7a7171;
    font-size: 2rem;
}
form .sp-form-html:first-child p:after {
    position: absolute;
    content: " ";
    display: block;
    border-bottom: solid 3px #730A13;
    bottom: -3px;
    width: 20%;
}

form .sp-form-html p span a {
    color: #085D7B;
    text-decoration: none;
}
こちらのCSSは、ページの最上部にあるテキストにのみあたるCSSとなっています。
見出しを最上部に設置しない場合は、設定できませんので、ご注意ください。
下線は、CSSで設定しているので、ビジュアル設定に合わせた色に変更してください。
ポイント②
利用規約へのリンクを設定しています。
ビジュアル設定でも利用規約へのリンク設置は可能となっていますが、
デザインをあてたい。や 規約分をそのまま表示させたい場合などは、ソース設定が必要となります。
ポイント③
強化ガジェットを導入しています。

● その他を選択した時に入力欄の活性化・非活性化を切り替える強化ガジェット
  → 業種とその他の欄をグループ化して使用
● チェック状態でボタンを活性化する強化ガジェット
  → 規約同意で送信可能
● ver.2でレコード値を自動発番できる強化ガジェット
  → オリジナル ID自動発番に使用

自動発番の強化ガジェットにてメール配信を行うため、APIキーの設定とDB項目に下記を追加しています。
APIメール送信 使用しない
ポイント④
テスト時はIP制限をかけてリリースしています。
リリースを行うと世の中にサイトが公開されます。
公開せず本番で確認したい場合などは、IP制限等を忘れずかけてください。
また、登録フォームを常に表示させるとデータがどんどん登録されてしまう可能性があります。
常に表示されている登録フォーム以外は、
ブロックのフォーム締切設定にて、「登録上限数」「登録期間(開始、終了)」を設定してください。

Web再申請ページ作成作成

手順1:認証ページの作成
認証エリアから認証用のページを作成します。
クリックログイン認証を使用するため、IDフィールドは、「申請番号」パスワードは、「なし」を選択してください。
「事務局差戻し」時のメール配信を行う処理は、アプリ(DB・メール)設計・構築 にて設定しています。
手順2:CSSの取得
登録フォームと同じデザインを更新フォームに反映します。
ver.2.19時点では、更新ブロックはビジュアル設定に対応していないため、ソース設定のみとなります。
ビジュアル設定と合わせるために登録フォームのCSSを取得する必要があります。
登録フォームの CSSについては、下記のにて取得することが可能です。

https://{お客様のドメイン}/_files/styles/insert-forms/{ブロックID}.css

ブロックIDは、詳細画面の基本設定(歯車マーク)から確認できます。
今回は、取得した下記のCSSをブロックのCSSに追加いたします。

CSS
.sp-form-container {
  font-size:16px;
  padding:1em;
  box-sizing:border-box;
  min-width:70.0%;
  color:#505050;
  background-color:#ffffff;
  border:1.0px solid #dddddd;
  border-radius:0.25rem;
}

.sp-form-container .sp-form-item:not(:last-child) {
  margin-bottom:0.5em;
  padding-bottom:0.5em;
}

.sp-form-field,
.sp-form-group {
  display:-webkit-box;
  display:-ms-flexbox;
  display:flex;
  -webkit-box-orient:vertical;
  -webkit-box-direction:normal;
  -ms-flex-direction:column;
  flex-direction:column;
  border-bottom:1.0px solid #dddddd;
}

.sp-form-field>.sp-form-label,
.sp-form-group>.sp-form-label {
  font-size:1.15em;
  font-weight:bold;
  padding:.25em .5em;
  word-break:break-all;
  box-sizing:border-box;
  color:#333333;
}

.sp-form-group-item>.sp-form-label {
  word-break:break-all;
  display:inline-block;
  margin-bottom:.2em;
}

.sp-form-field>.sp-form-data,
.sp-form-group>.sp-form-data {
  display:-webkit-box;
  display:-ms-flexbox;
  display:flex;
  -webkit-box-orient:vertical;
  -webkit-box-direction:normal;
  -ms-flex-direction:column;
  flex-direction:column;
  word-break:break-all;
  padding:1em;
  box-sizing:border-box;
}

.sp-form-group-item>.sp-form-data {
  display:-webkit-box;
  display:-ms-flexbox;
  display:flex;
  -webkit-box-orient:vertical;
  -webkit-box-direction:normal;
  -ms-flex-direction:column;
  flex-direction:column;
}

.sp-form-required {
  display:inline-block;
  margin:0 .5em;
  line-height:1;
  border-radius:.25em;
  font-size:.8em;
  color:#d91438;
  padding:0;
}

.sp-form-group-item:not(:last-child) { margin-bottom:.5em; }

.sp-form-noted {
  font-size:.8em;
  color:#808080;
  word-break:break-all;
  margin-top:.5em;
}

.sp-form-error {
  font-size:.8em;
  color:#d91438;
}

.sp-form-control {
  -moz-appearance:none;
  -webkit-appearance:none;
  -ms-progress-appearance:none;
  appearance:none;
  font-family:inherit;
  font-size:1em;
  line-height:1.5;
  padding:.3em .7em;
  color:#333333;
  box-sizing:border-box;
  width:100%;
  margin-bottom:.2em;
  border:1px solid #dddddd;
  border-radius:0.25rem;
}

.sp-form-control:placeholder-shown { color:#aaa; }

.sp-form-control::placeholder { color:#aaa; }

.sp-form-control::-ms-input-placeholder { color:#aaa; }

.sp-form-control:-ms-input-placeholder { color:#aaa; }

.sp-form-control:-moz-placeholder { color:#aaa; }

textarea.sp-form-control { resize:vertical; }

select.sp-form-control,
option.sp-form-control {
  -moz-appearance:none;
  -webkit-appearance:none;
  -ms-progress-appearance:none;
  appearance:none;
  padding-right:1.5em;
}

select.sp-form-control::-ms-expand { display:none; }

.sp-form-phone .sp-form-control { max-width:20em; }

.sp-form-phone>*:not(:only-child) { margin-right:.5rem; }

.sp-form-dropdown { position:relative; }

.sp-form-dropdown-icon {
  display:block;
  position:absolute;
  top:1em;
  right:.5em;
  line-height:0;
  pointer-events:none;
}

.sp-form-dropdown-icon:after {
  content:"";
  display:block;
  border-top:0.333em solid #888;
  border-right:.333em solid transparent;
  border-left:.333em solid transparent;
}

.sp-form-selection {
  display:block;
  margin:.25em 0;
  padding:.5em .8em .5em 0;
  border-radius:0.25rem;
}

.sp-form-selection-label { vertical-align:middle; }

.sp-form-datetimes,
.sp-form-date,
.sp-form-time,
.sp-form-timezone {
  display:-webkit-box;
  display:-ms-flexbox;
  display:flex;
  -webkit-box-orient:horizontal;
  -webkit-box-direction:normal;
  -ms-flex-flow:row wrap;
  flex-flow:row wrap;
  -webkit-box-align:center;
  -ms-flex-align:center;
  align-items:center;
}

.sp-form-datetime,
.sp-form-date,
.sp-form-time,
.sp-form-timezone {
  margin-right:.5rem;
  -ms-flex-wrap:nowrap;
  flex-wrap:nowrap;
}

.sp-form-datetime { max-width:20em; }

.sp-form-phone {
  display:-webkit-box;
  display:-ms-flexbox;
  display:flex;
  -webkit-box-orient:horizontal;
  -webkit-box-direction:normal;
  -ms-flex-flow:row wrap;
  flex-flow:row wrap;
  -webkit-box-align:center;
  -ms-flex-align:center;
  align-items:center;
}

.sp-form-date-separator {
  width:1em;
  text-align:center;
  -ms-flex-negative:1;
  flex-shrink:0;
}

.sp-form-number { max-width:20em; }

.sp-form-email-reenter {
  font-size:.9em;
  margin-bottom:.2em;
}

.sp-form-html p { margin:0; }

.sp-form-interaction {
  display:-webkit-box;
  display:-ms-flexbox;
  display:flex;
  -ms-flex-wrap:wrap;
  flex-wrap:wrap;
  margin-top:1em;
}

.sp-form-prev-button {
  color:#730a13;
  background-color:#f2f2f2;
  border:1.0px solid #ffffff;
  border-radius:0.25rem;
}

.sp-form-next-button {
  color:#ffffff;
  background-color:#730a13;
  border:none;
  border-radius:0.25rem;
}

.sp-form-field .sp-form-embedded { padding-left:.25em; }

.sp-form-selection>input[type="radio"],
.sp-form-selection>input[type="checkbox"] {
  vertical-align:middle;
  margin-left:0;
}

.sp-form-selection>input[type="radio"] { margin-top:0; }

.sp-form-date>input,
.sp-form-time>input { max-width:7em; }

.sp-form-interaction>button {
  -webkit-box-flex:1;
  -ms-flex-positive:1;
  flex-grow:1;
  cursor:pointer;
  font-size:1em;
  line-height:1.5;
  margin:.5rem;
  padding:.375rem 0;
  text-align:center;
  -webkit-user-select:none;
  -moz-user-select:none;
  -ms-user-select:none;
  user-select:none;
  white-space:nowrap;
}

@media (min-width:768px) {
  .sp-form-container {
    font-size:initial;
    padding:3em;
    margin:0 auto;
    width:70.0%;
  }

  .sp-form-field,
  .sp-form-group {
    -webkit-box-orient:horizontal;
    -webkit-box-direction:normal;
    -ms-flex-flow:row nowrap;
    flex-flow:row nowrap;
  }

  .sp-form-field>.sp-form-label,
  .sp-form-group>.sp-form-label {
    font-size:1em;
    width:30%;
    padding:1em;
  }

  .sp-form-group .sp-form-group-item>.sp-form-label {
    font-size:.9em;
    padding-right:.5em;
  }

  .sp-form-field>.sp-form-data,
  .sp-form-group>.sp-form-data {
    font-size:1em;
    width:70%;
  }

  .sp-form-group>.sp-form-data {
    -webkit-box-orient:horizontal;
    -webkit-box-direction:normal;
    -ms-flex-flow:row wrap;
    flex-flow:row wrap;
  }

  .sp-form-group.sp-form-group-vertical>.sp-form-data {
    -webkit-box-orient:vertical;
    -webkit-box-direction:normal;
    -ms-flex-direction:column;
    flex-direction:column;
  }

  .sp-form-group-item { padding:.25em; }

  .sp-form-group-item:not(:last-child) { margin-bottom:0; }

  .sp-form-control { font-size:.9em; }

  .sp-form-selection {
    font-size:.9em;
    margin:0 1em 0 0;
    padding:0;
  }

  .sp-form-selection-vertical {
    display:-webkit-box;
    display:-ms-flexbox;
    display:flex;
    -webkit-box-orient:vertical;
    -webkit-box-direction:normal;
    -ms-flex-direction:column;
    flex-direction:column;
  }

  .sp-form-selection-horizontal {
    display:-webkit-box;
    display:-ms-flexbox;
    display:flex;
    -webkit-box-orient:horizontal;
    -webkit-box-direction:normal;
    -ms-flex-flow:row wrap;
    flex-flow:row wrap;
  }

  .sp-form-interaction {
    justify-content:center;
    margin-top:2em;
  }

  .sp-form-embedded { font-size:.9em; }

  .sp-form-group-item .sp-form-embedded { padding-right:5em; }

  .sp-form-interaction>button {
    -webkit-box-flex:0;
    -ms-flex-positive:0;
    flex-grow:0;
    padding:.375rem 5em;
  }
}

.sp-form-recaptcha {
  display:-webkit-box;
  display:-ms-flexbox;
  display:flex;
  -webkit-box-pack:start;
  -ms-flex-pack:start;
  justify-content:flex-start;
}

.sp-form-recaptcha-right {
  display:-webkit-box;
  display:-ms-flexbox;
  display:flex;
  -webkit-box-pack:end;
  -ms-flex-pack:end;
  justify-content:flex-end;
}

.sp-form-recaptcha-center {
  display:-webkit-box;
  display:-ms-flexbox;
  display:flex;
  -webkit-box-pack:center;
  -ms-flex-pack:center;
  justify-content:center;
}

.sp-form-file-button {
  padding:4.875px 9.75px;
  font-size:80%;
  cursor:pointer;
  color:#730a13;
  background-color:#f2f2f2;
  border:none;
  border-radius:0.25rem;
}

.sp-form-file-button:focus { outline:0; }

.sp-from-file-default-drag-drop-area {
  color:#333333;
  background-color:#f8f8f8;
  border:1.0px dashed #6c757d;
  border-radius:0;
  width:100%;
  height:200px;
  text-align:center;
}

.sp-from-file-ondraghover-drag-drop-area {
  color:#333333;
  background-color:#efefef;
  border:1.0px dashed #6c757d;
  border-radius:0;
  width:100%;
  height:200px;
  text-align:center;
}

.sp-from-file-ondragleave-drag-drop-area {
  color:#333333;
  background-color:#f8f8f8;
  border:1.0px dashed #6c757d;
  border-radius:0;
  width:100%;
  height:200px;
}

.sp-from-file-ondrop-drag-drop-area {
  color:#333333;
  background-color:#f8f8f8;
  border:1.0px dashed #6c757d;
  border-radius:0;
  width:100%;
  height:200px;
}

.sp-form-embedded>.sp-file-info:last-child { padding-bottom:0; }

.sp-file-info {
  padding-top:1em;
  padding-bottom:1em;
  line-height:1.5;
}

.sp-file-info>div { width:100%; }
ページの head より CSS を直接読み込む形で実装していただいても問題ありません。
手順3:更新ブロックのHTML作成
認証ページの作成を行うと、自動的に更新ページ及びブロックが生成されます。
このブロックをページに合わせて修正します。

▼フィールド一覧
フィールド 使用状況
【申請者向け】
事務局担当者コメント入力
表示のみ
申請番号 表示のみ
氏名 入力項目
会社名 入力項目
郵便番号 入力項目
都道府県 入力項目
市区町村・番地 入力項目
ビル名・部屋番号等 入力項目
電話番号 入力項目
メールアドレス 入力項目
業種 入力項目
業種_その他 入力項目
書類ファイル 入力項目
同意 入力項目
ステータス(事務局担当者) 使用しない ※ 管理項目のため
ステータス(事務局長) 使用しない ※ 管理項目のため
ステータス(申請者-再申請) 使用しない ※ 管理項目のため
ステータス(共通) 使用しない ※ 管理項目のため
【事務局長向け】
事務局担当者コメント入力
使用しない ※ 管理項目のため
【事務局担当者向け】
事務局長コメント入力
使用しない ※ 管理項目のため

HTMLは、下記の内容を更新フォームに貼り付けます。
フィールドIDは、フィールド作成時の状況によってことなる可能性があるので、環境に合わせて修正してください。

入力 - HTML
<div class="sp-form-container">
   <div class="sp-form-item sp-form-html"><p>Web再申請(差し戻し)</p></div> 
  <div class="sp-form-item sp-form-field">
    <div class="sp-form-label">
      事務局コメント
    </div>
    <div class="sp-form-data">
      <span class="sp-form-embedded">
      <th:block th:each="line, stat : ${siteClient.record[21]?.lines}">
        <th:block th:text="${line}">
          Example
        </th:block>
        <br th:unless="${stat.last}">
      </th:block>
    </span>
    </div>
  </div>
  
  <sp:input-field name="f01"></sp:input-field> 
    <div class="sp-form-item sp-form-field">
    <div class="sp-form-label">
      申請番号
    </div>
    <div class="sp-form-data">
      <span class="sp-form-embedded" th:text="${siteClient.record[1]}">Example</span>
    </div>
  </div>

  <!--/* 氏名(name) */--> 
  <sp:input-field name="f02"></sp:input-field> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label"> 
      <th:block th:text="${fields['f02'].label}">
        Label
      </th:block> 
      <span class="sp-form-required" th:if="${fields['f02'].required}" th:text="${fields['f02'].requiredIndicator}">*</span>
    </div> 
    <div class="sp-form-data">
      <input type="text" class="sp-form-control" name="f02" th:value="${#maps.containsKey(inputs, 'f02') ? inputs['f02'] : siteClient.record[2]}">
      <span class="sp-form-noted" th:if="${fields['f02'].help != null}" th:text="${fields['f02'].help}">Help text</span>
      <span class="sp-form-error" th:if="${errors['f02'] != null}" th:text="${errors['f02'].message}">Error message</span>
    </div> 
  </div> 
  <!--/* 会社名(company) */--> 
  <sp:input-field name="f03"></sp:input-field> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label"> 
      <th:block th:text="${fields['f03'].label}">
        Label
      </th:block> 
      <span class="sp-form-required" th:if="${fields['f03'].required}" th:text="${fields['f03'].requiredIndicator}">*</span>
    </div> 
    <div class="sp-form-data">
      <input type="text" class="sp-form-control" name="f03" th:value="${#maps.containsKey(inputs, 'f03') ? inputs['f03'] : siteClient.record[3]}">
      <span class="sp-form-noted" th:if="${fields['f03'].help != null}" th:text="${fields['f03'].help}">Help text</span>
      <span class="sp-form-error" th:if="${errors['f03'] != null}" th:text="${errors['f03'].message}">Error message</span>
    </div> 
  </div> 
  <!--/* 郵便番号(zipCode) */--> 
  <sp:input-field name="f04"></sp:input-field> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label"> 
      <th:block th:text="${fields['f04'].label}">
        Label
      </th:block> 
      <span class="sp-form-required" th:if="${fields['f04'].required}" th:text="${fields['f04'].requiredIndicator}">*</span>
    </div> 
    <div class="sp-form-data">
      <input type="text" class="sp-form-control" name="f04" th:value="${#maps.containsKey(inputs, 'f04') ? inputs['f04'] : siteClient.record[4]}">
      <span class="sp-form-noted" th:if="${fields['f04'].help != null}" th:text="${fields['f04'].help}">Help text</span>
      <span class="sp-form-error" th:if="${errors['f04'] != null}" th:text="${errors['f04'].message}">Error message</span>
    </div> 
  </div> 
  <!--/* 都道府県(pref) */-->
  <sp:input-field name="f05"></sp:input-field>
  <div class="sp-form-item sp-form-field">
    <div class="sp-form-label">
      <th:block th:text="${fields['f05'].label}">
        Label
      </th:block>
      <span class="sp-form-required" th:if="${fields['f05'].required}" th:text="${fields['f05'].requiredIndicator}">*</span>
    </div>
    <div class="sp-form-data">
    <div class="sp-form-dropdown">
      <select class="sp-form-control" name="f05" th:with="default=${#maps.containsKey(inputs, 'f05') ? inputs['f05'] : #strings.toString(siteClient.record[5]?.id)}">
        <option value="" th:text="${fields['f05'].unselectedLabel}" th:selected="${default == null}">Select option</option>
        <option th:each="option : ${fields['f05'].options}" th:value="${option.id}" th:text="${option.label}" th:selected="${default == #strings.toString(option.id)}">Item</option>
      </select>
      <span class="sp-form-dropdown-icon"></span>
    </div>
    <span class="sp-form-noted" th:if="${fields['f05'].help != null}" th:text="${fields['f05'].help}">Help text</span>
    <span class="sp-form-error" th:if="${errors['f05'] != null}" th:text="${errors['f05'].message}">Error message</span>
    </div>
  </div>
  <!--/* 市区町村・番地(address1) */--> 
  <sp:input-field name="f06"></sp:input-field> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label"> 
      <th:block th:text="${fields['f06'].label}">
        Label
      </th:block> 
      <span class="sp-form-required" th:if="${fields['f06'].required}" th:text="${fields['f06'].requiredIndicator}">*</span>
    </div> 
    <div class="sp-form-data">
      <input type="text" class="sp-form-control" name="f06" th:value="${#maps.containsKey(inputs, 'f06') ? inputs['f06'] : siteClient.record[6]}">
      <span class="sp-form-noted" th:if="${fields['f06'].help != null}" th:text="${fields['f06'].help}">Help text</span>
      <span class="sp-form-error" th:if="${errors['f06'] != null}" th:text="${errors['f06'].message}">Error message</span>
    </div> 
  </div> 
  <!--/* ビル名・部屋番号等(address2) */--> 
  <sp:input-field name="f07"></sp:input-field> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label"> 
      <th:block th:text="${fields['f07'].label}">
        Label
      </th:block> 
      <span class="sp-form-required" th:if="${fields['f07'].required}" th:text="${fields['f07'].requiredIndicator}">*</span>
    </div> 
    <div class="sp-form-data">
      <input type="text" class="sp-form-control" name="f07" th:value="${#maps.containsKey(inputs, 'f07') ? inputs['f07'] : siteClient.record[7]}">
      <span class="sp-form-noted" th:if="${fields['f07'].help != null}" th:text="${fields['f07'].help}">Help text</span>
      <span class="sp-form-error" th:if="${errors['f07'] != null}" th:text="${errors['f07'].message}">Error message</span>
    </div> 
  </div> 
  <!--/* 電話番号(phone) */--> 
  <sp:input-field name="f08"></sp:input-field> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label"> 
      <th:block th:text="${fields['f08'].label}">
        Label
      </th:block> 
      <span class="sp-form-required" th:if="${fields['f08'].required}" th:text="${fields['f08'].requiredIndicator}">*</span>
    </div> 
    <div class="sp-form-data"> 
      <div class="sp-form-phone"> 
        <div class="sp-form-dropdown" th:if="${fields['f08'].countryCode == null}">
          <select class="sp-form-control" name="f08:code" th:with="defaultCountryCode=${#maps.containsKey(inputs, 'f08:code') ? inputs['f08:code'] : siteClient.record[8]?.countryCode?.country?.alpha2Code}">
            <option value="" th:text="${fields['f08'].unselectedCodeLabel}" th:selected="${defaultCountryCode == null}">Select option</option>
            <option th:each="countryCode : ${fields['f08'].countryCodes}" th:value="${countryCode.country.alpha2Code}" th:text="|${countryCode.country.alpha2Code}(+${countryCode.code})|" th:selected="${defaultCountryCode == countryCode.country.alpha2Code}">Item</option>
          </select>
          <span class="sp-form-dropdown-icon"></span>
        </div> 
        <input type="tel" class="sp-form-control" name="f08" th:value="${#maps.containsKey(inputs, 'f08') ? inputs['f08'] : siteClient.record[8]?.nationalNumber}">
      </div> 
      <span class="sp-form-noted" th:if="${fields['f08'].help != null}" th:text="${fields['f08'].help}">Help text</span>
      <span class="sp-form-error" th:if="${errors['f08'] != null}" th:text="${errors['f08'].message}">Error message</span>
    </div> 
  </div> 
  <!--/* メールアドレス(mail) */--> 
  <sp:input-field name="f09"></sp:input-field> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label"> 
      <th:block th:text="${fields['f09'].label}">
        Label
      </th:block> 
      <span class="sp-form-required" th:if="${fields['f09'].required}" th:text="${fields['f09'].requiredIndicator}">*</span>
    </div> 
    <div class="sp-form-data">
      <input type="email" class="sp-form-control" name="f09" th:value="${#maps.containsKey(inputs, 'f09') ? inputs['f09'] : siteClient.record[9]}"> 
      <div th:if="${fields['f09'].collation}">
        <span class="sp-form-email-reenter" th:text="${fields['f09'].reenterLabel}">Re-enter to confirm</span>
        <input type="email" class="sp-form-control" name="f09:reenter" th:value="${#maps.containsKey(inputs, 'f09:reenter') ? inputs['f09:reenter'] : siteClient.record[9]}">
      </div> 
      <span class="sp-form-noted" th:if="${fields['f09'].help != null}" th:text="${fields['f09'].help}">Help text</span>
      <span class="sp-form-error" th:if="${errors['f09'] != null}" th:text="${errors['f09'].message}">Error message</span>
    </div> 
  </div> 
  <!--/* 業種(type) */--> 
  <!--/* 業種_その他(typeOther) */--> 
  <div class="sp-form-item sp-form-field">
    <div class="sp-form-label">
      <th:block th:text="${fields['f010'].label}">
        Label
      </th:block>
      <span class="sp-form-required" th:if="${fields['f010'].required}" th:text="${fields['f010'].requiredIndicator}">*</span>
    </div>
    <div class="sp-form-data"> 
      <div class="sp-form-group-item">
        <label class="sp-form-label">[ 業種 ]</label> 
        <div class="sp-form-data">
          <sp:input-field name="f010"></sp:input-field> 
          <div class="sp-form-dropdown">
            <select class="sp-form-control" name="f010" th:with="default=${#maps.containsKey(inputs, 'f010') ? inputs['f010'] : #strings.toString(siteClient.record[10]?.id)}">
              <option value="" th:text="${fields['f010'].unselectedLabel}" th:selected="${default == null}">Select option</option>
              <option th:each="option : ${fields['f010'].options}" th:value="${option.id}" th:text="${option.label}" th:selected="${default == #strings.toString(option.id)}">Item</option>
            </select>
            <span class="sp-form-dropdown-icon"></span>
          </div>
          <span class="sp-form-noted" th:if="${fields['f010'].help != null}" th:text="${fields['f010'].help}">Help text</span>
          <span class="sp-form-error" th:if="${errors['f010'] != null}" th:text="${errors['f010'].message}">Error message</span>
        </div>
      </div> 
      <div class="sp-form-group-item">
        <label class="sp-form-label">[ その他 ]</label> 
        <div class="sp-form-data">
          <sp:input-field name="f011"></sp:input-field> 
          <input type="text" class="sp-form-control" name="f011" th:value="${#maps.containsKey(inputs, 'f011') ? inputs['f011'] : siteClient.record[11]}">
          <span class="sp-form-noted" th:if="${fields['f011'].help != null}" th:text="${fields['f011'].help}">Help text</span>
          <span class="sp-form-error" th:if="${errors['f011'] != null}" th:text="${errors['f011'].message}">Error message</span>
        </div> 
      </div> 
    </div>
  </div>
  <!--/* 書類ファイル(file) */--> 
  <sp:input-field name="f012"></sp:input-field> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label"> 
      <th:block th:text="${fields['f012'].label}">
        Label
      </th:block> 
      <span class="sp-form-required" th:if="${fields['f012'].required}" th:text="${fields['f012'].requiredIndicator}">*</span>
    </div> 
    <div class="sp-form-data"> 
      <div name="fileInfoWrapf012">
        <input type="hidden" name="f012" th:value="${#maps.containsKey(inputs, 'f012') ? inputs['f012'] : siteClient.record[12]}">
      </div> 
      <span class="sp-form-noted" th:if="${fields['f012'].help != null}" th:text="${fields['f012'].help}">Help text</span>
      <span class="sp-form-error" th:if="${errors['f012'] != null}" th:text="${errors['f012'].message}">Error message</span>
    </div> 
  </div> 
  <div class="sp-form-item sp-form-html"><p style="text-align: center;"><br></p><p style="text-align: center;"><span style="color: rgb(0, 0, 0);">【 <a href="#" target="_blank" behavior="redirect">利用規約</a> 】に同意の上、『次へ』ボタンを押してください</span></p></div>
  <!--/* 同意(agreement) */--> 
  <sp:input-field name="f013"></sp:input-field> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label"> 
      <th:block th:text="${fields['f013'].label}">
        Label
      </th:block> 
      <span class="sp-form-required" th:if="${fields['f013'].required}" th:text="${fields['f013'].requiredIndicator}">*</span>
    </div> 
    <div class="sp-form-data"> 
      <div class="sp-form-selection-vertical">
        <label class="sp-form-selection" th:with="default=${#maps.containsKey(inputs, 'f013') ? inputs['f013'] : siteClient.record[13]?.![#strings.toString(id)]}" th:each="option : ${fields['f013'].options}">
          <input type="checkbox" name="f013" th:value="${option.id}" th:checked="${default != null ? #lists.contains(default, #strings.toString(option.id)) : false}">
          <span class="sp-form-selection-label" th:text="${option.label}">Item</span>
        </label>
      </div> 
      <span class="sp-form-noted" th:if="${fields['f013'].help != null}" th:text="${fields['f013'].help}">Help text</span>
      <span class="sp-form-error" th:if="${errors['f013'] != null}" th:text="${errors['f013'].message}">Error message</span>
    </div> 
  </div> 
  <div class="sp-form-item sp-form-interaction">
    <button class="sp-form-prev-button" type="submit" name="action" value="previous" th:if="!${step.isFirst}" th:text="${step.prevButtonLabel}">Prev</button>
    <button class="sp-form-next-button" type="submit" name="action" value="next" th:text="${step.nextButtonLabel}">Next</button>
  </div> 
</div>
確認 - HTML
<div class="sp-form-container">
  <div class="sp-form-item sp-form-html"><p>Web再申請(差し戻し)</p></div> 
  <div class="sp-form-item sp-form-field">
    <div class="sp-form-label">
      事務局コメント
    </div>
    <div class="sp-form-data">
      <span class="sp-form-embedded">
      <th:block th:each="line, stat : ${siteClient.record[21]?.lines}">
        <th:block th:text="${line}">
          Example
        </th:block>
        <br th:unless="${stat.last}">
      </th:block>
    </span>
    </div>
  </div>

  <!--/* 申請番号(number) */--> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label" th:text="${fields['f01'].label}">
      Label
    </div> 
    <div class="sp-form-data">
      <span class="sp-form-embedded" th:text="${inputs['f01']}">Example</span>
    </div> 
  </div> 
  <!--/* 氏名(name) */--> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label" th:text="${fields['f02'].label}">
      Label
    </div> 
    <div class="sp-form-data">
      <span class="sp-form-embedded" th:text="${inputs['f02']}">Example</span>
    </div> 
  </div> 
  <!--/* 会社名(company) */--> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label" th:text="${fields['f03'].label}">
      Label
    </div> 
    <div class="sp-form-data">
      <span class="sp-form-embedded" th:text="${inputs['f03']}">Example</span>
    </div> 
  </div> 
  <!--/* 郵便番号(zipCode) */--> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label" th:text="${fields['f04'].label}">
      Label
    </div> 
    <div class="sp-form-data">
      <span class="sp-form-embedded" th:text="${inputs['f04']}">Example</span>
    </div> 
  </div> 
  <!--/* 都道府県(pref) */--> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label" th:text="${fields['f05'].label}">
      Label
    </div> 
    <div class="sp-form-data">
      <span class="sp-form-embedded" th:each="option : ${fields['f05'].options}" th:if="${inputs['f05'] == #strings.toString(option.id)}" th:text="${option.label}">Item</span>
    </div> 
  </div> 
  <!--/* 市区町村・番地(address1) */--> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label" th:text="${fields['f06'].label}">
      Label
    </div> 
    <div class="sp-form-data">
      <span class="sp-form-embedded" th:text="${inputs['f06']}">Example</span>
    </div> 
  </div> 
  <!--/* ビル名・部屋番号等(address2) */--> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label" th:text="${fields['f07'].label}">
      Label
    </div> 
    <div class="sp-form-data">
      <span class="sp-form-embedded" th:text="${inputs['f07']}">Example</span>
    </div> 
  </div> 
  <!--/* 電話番号(phone) */--> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label" th:text="${fields['f08'].label}">
      Label
    </div> 
    <div class="sp-form-data">
      <span class="sp-form-embedded" th:text="${inputs['f08']}">+81 03-1234-5678</span>
    </div> 
  </div> 
  <!--/* メールアドレス(mail) */--> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label" th:text="${fields['f09'].label}">
      Label
    </div> 
    <div class="sp-form-data">
      <span class="sp-form-embedded" th:text="${inputs['f09']}">spiral@example.com</span>
    </div> 
  </div> 
  <!--/* 業種(type) */--> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label" th:text="${fields['f010'].label}">
      Label
    </div> 
    <div class="sp-form-data"> 
      <div class="sp-form-group-item">
        <label class="sp-form-label">[ 業種 ]</label> 
        <div class="sp-form-data">
          <span class="sp-form-embedded" th:each="option : ${fields['f010'].options}" th:if="${inputs['f010'] == #strings.toString(option.id)}" th:text="${option.label}">Item</span>
        </div> 
      </div> 
      <div class="sp-form-group-item">
        <label class="sp-form-label">[ その他 ]</label> 
        <div class="sp-form-data">
          <span class="sp-form-embedded" th:text="${inputs['f011']}">Example</span>
        </div> 
      </div> 
    </div>
  </div> 
  <!--/* 書類ファイル(file) */--> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label" th:text="${fields['f012'].label}">
      Label
    </div> 
    <div class="sp-form-data">
      <span class="sp-form-embedded" name="file-field-f012" th:text="${inputs['f012']}"></span>
    </div> 
  </div> 
  <!--/* 同意(agreement) */--> 
  <div class="sp-form-item sp-form-field"> 
    <div class="sp-form-label" th:text="${fields['f013'].label}">
      Label
    </div> 
    <div class="sp-form-data"> 
      <div class="sp-form-selection-vertical">
        <span class="sp-form-embedded" th:each="option : ${fields['f013'].options}" th:if="${inputs['f013'] != null ? #lists.contains(inputs['f013'], #strings.toString(option.id)) : false}" th:text="${option.label}">Item</span>
      </div> 
    </div> 
  </div> 
  <div class="sp-form-item sp-form-interaction">
    <button class="sp-form-prev-button" type="submit" name="action" value="previous" th:if="!${step.isFirst}" th:text="${step.prevButtonLabel}">戻る</button>
    <button class="sp-form-next-button" type="submit" name="action" value="next" th:text="${step.nextButtonLabel}">次へ</button>
  </div>
</div>
手順4:更新ページに更新フォームのブロックを埋め込み
ステータスが「事務局差戻し」の場合のみ、ブロックが表示される分岐処理と共にブロックを設置します。

HTML
<!--/* 事務局差し戻しの場合 */-->
<th:block th:if="${siteClient.record[20]?.id eq 2}">
    <sp:block name="xxxx"></sp:block>
</th:block>
<th:block th:if="${siteClient.record[20]?.id ne 2}">
    <p>変更できません。</p>
</th:block>
「siteClient.record[20]」の「20」は共通ステータスのフィールドIDとなります。
フィールド作成時の状況によってことなる可能性があるので、環境に合わせて修正してください。

「sp:block」及びの箇所は環境によってことなるため、自身の環境に合わせて修正してください。
手順5:差戻し時メールにクリックログインURLを設置
非同期トリガにて作成したメールにクリックログインURLを設置します。
クリックログインをメール設定するには、認証エリアを本番公開する必要があります。
認証エリア単体では動作しない画面となりますので、認証エリアのみリリースを行い、
非同期トリガにて作成したメールにクリックログインURLを設置してください。
手順6:動作確認
本番環境にて動作確認を行います。下記のポイントを確認してください。
1. アプリにて、事務局差戻し時に送られるメールにクリックログインが設置されている
2. メール内のリンクに遷移し、差戻し再申請の画面が表示されている
3. 前回登録内容及び、事務局のコメントが表示されている
4. 申請フォームと同じデザインになっている
5. 再申請がエラーなく行われる
6. 再申請後にメール内のリンクにアクセスすると、エラーが表示される
上記を確認いただき問題なければ、完了となります。
ポイント①
見出しやグループ化しているフィールドは、登録フォームから移設となります。
入力だけでなく、確認も忘れず追加をお願いします。

グループ化しているフィールド
  <div class="sp-form-item sp-form-field">
    <div class="sp-form-label">
      <th:block th:text="${fields['f010'].label}">
        Label
      </th:block>
      <span class="sp-form-required" th:if="${fields['f010'].required}" th:text="${fields['f010'].requiredIndicator}">*</span>
    </div>
    <div class="sp-form-data"> 
      <div class="sp-form-group-item">
        <label class="sp-form-label">[ 業種 ]</label> 
        <div class="sp-form-data">
          <sp:input-field name="f010"></sp:input-field> 
          <div class="sp-form-dropdown">
            <select class="sp-form-control" name="f010" th:with="default=${#maps.containsKey(inputs, 'f010') ? inputs['f010'] : #strings.toString(siteClient.record[10]?.id)}">
              <option value="" th:text="${fields['f010'].unselectedLabel}" th:selected="${default == null}">Select option</option>
              <option th:each="option : ${fields['f010'].options}" th:value="${option.id}" th:text="${option.label}" th:selected="${default == #strings.toString(option.id)}">Item</option>
            </select>
            <span class="sp-form-dropdown-icon"></span>
          </div>
          <span class="sp-form-noted" th:if="${fields['f010'].help != null}" th:text="${fields['f010'].help}">Help text</span>
          <span class="sp-form-error" th:if="${errors['f010'] != null}" th:text="${errors['f010'].message}">Error message</span>
        </div>
      </div> 
      <div class="sp-form-group-item">
        <label class="sp-form-label">[ その他 ]</label> 
        <div class="sp-form-data">
          <sp:input-field name="f011"></sp:input-field> 
          <input type="text" class="sp-form-control" name="f011" th:value="${#maps.containsKey(inputs, 'f011') ? inputs['f011'] : siteClient.record[11]}">
          <span class="sp-form-noted" th:if="${fields['f011'].help != null}" th:text="${fields['f011'].help}">Help text</span>
          <span class="sp-form-error" th:if="${errors['f011'] != null}" th:text="${errors['f011'].message}">Error message</span>
        </div> 
      </div> 
    </div>
  </div>
ポイント②
ページにブロックを埋め込む際に
ステータスが「事務局差戻し」の場合のみ、ブロックが表示される分岐処理と共にブロックを設置します。

エラー文章をフリーコンテンツのブロックを作成し、埋め込むこともできます。

<!--/* 事務局差し戻しの場合 */-->
<th:block th:if="${siteClient.record[20]?.id eq 2}">
    <sp:block name="xxxx"></sp:block>
</th:block>
<!--/* 事務局差し戻し以外の場合 */-->
<th:block th:if="${siteClient.record[20]?.id ne 2}">
    <!--/* ここにフリーコンテンツを埋め込む */-->
</th:block>
ポイント③
見出しやリンクのデザインを共通ソースに入れていない場合は、更新ページにも下記のCSSを追加します。
CSS
form .sp-form-html:first-child {
    margin-bottom: 40px !important;
    margin: auto;
}
form .sp-form-html:first-child p {
    border-bottom: solid 3px #D91438;
    position: relative;
    color: #7a7171;
    font-size: 2rem;
}
form .sp-form-html:first-child p:after {
    position: absolute;
    content: " ";
    display: block;
    border-bottom: solid 3px #730A13;
    bottom: -3px;
    width: 20%;
}

form .sp-form-html p span a {
    color: #085D7B;
    text-decoration: none;
}
ポイント④
登録フォームと同様に、更新フォームでも強化ガジェットを追加します。
● その他を選択した時に入力欄の活性化・非活性化を切り替える強化ガジェット
 → 業種とその他の欄をグループ化して使用
● チェック状態でボタンを活性化する強化ガジェット
 → 規約同意で送信可能

IDの発番は、完了しているため、自動発番できる強化ガジェットは不要です。
● ver.2でレコード値を自動発番できる強化ガジェット

最後に

設定後は動作確認を必ず行い、動作に問題がないか確認をしてください。
また、不具合やほかのやり方が知りたい等あれば、下記の「コンテンツに関しての要望はこちら」からご連絡ください。

サイト設計・構築が完了したので次はユーザ・アプリロール・グループ設定に進みます。
関連記事はこちら
コンテンツに関しての
要望はこちら