この記事で分かること
この記事は、Notes/Domino のアプリを使っている方全般に向けた記事です。 Notes のフォームを WEB フォームに作り直すときに、これまでの書き方をどこへ移せばよいかが分かります。
Notes のフォームは、QueryOpen → PostOpen → (入力)→ QuerySave → PostSave → QueryClose と、イベントが順に起きる前提で作られています。
consentFlow の WEB フォームは、一見、これらにそのまま当たるイベントがありません。
ただし、同じ目的を果たす書き場所は用意されています。
この記事では、Notes のフォームイベントやフィールド式を WEB フォームの「どこに書くか」を対応表にまとめ、画面側(フォームビルダー)で済ませるものと、サーバー側(プロコードのフック)に置くものの分け方を説明します。
対象: Notes/Domino のユーザー全般。
Notes のフォームを WEB フォームに作り直す方、プロコード開発を担当する方。
consentFlow 4.4.0 以降(4.4.0 より前の環境での PostOpen の置き換えは、関連記事「1回だけ処理を実行する」の末尾を参照)。
前提: 考え方の違い
| Notes のフォーム | consentFlow の WEB フォーム | |
|---|---|---|
| 動く仕組み | イベント(QueryOpen、PostOpen、Exiting、QuerySave…)が決まった順に起きる | 各フィールドに付けた式(計算値・条件表示・検証)が、開いたときと値が変わるたびに評価される |
| 書き方の中心 | 「いつ」動くかをイベントごとに書く | 「どんな条件のとき」どうなるかをフィールドごとに書く |
| 再計算 | F9 や保存のときに式を再計算する | 値が変わると、それに依存する式が自動で再評価される |
| 確定処理(採番、履歴、連携) | QuerySave / PostSave に書く | 画面側ではなく、サーバー側のプロコードのフックか、Notes エージェントの呼び出し設定に置く |
つまり、「PostOpen に書いていた処理」をそのまま 1 か所に移す場所はなく、目的ごとに置き場所を選びます。
対応表: Notes のイベント → WEB フォームの書き場所

フォームを開くとき
| Notes | 目的 | WEB フォームでの書き場所 | 補足 |
|---|---|---|---|
| QueryOpen | 開く前の判定、表示の準備 | サーバー側: customFormBeforePageLoad()(表示前)/ customFormAfterPageLoad()(表示後) | 画面側で「開かせない」制御はしません。見せる・見せないは条件表示で |
| PostOpen | 開いた直後に初期値を入れる、マスタを 1 回読む | フォームスクリプト(予約キー scriptBlock)に cfAPI.form.onOpen(fn) を登録 | ページ表示ごとに 1 回だけ呼ばれ、部分更新で再実行されません。コールバックの中で ctx.set('キー', 値) で項目に書きます(関連記事「1回だけ処理を実行する」) |
| PostOpen(新規作成時だけ) | 作成時刻・作成者・作成時点の所属を記録 | フォームスクリプトの cfAPI.form.onNew(fn) | 新規作成のときだけ 1 回。保存する非表示フィールドに書きます |
| (既存文書のデータ移行) | 古い文書を開いたときに値を直す | フォームスクリプトの cfAPI.form.migrate(番号, fn) | 未実施の文書を編集モードで開いたとき、番号の昇順に 1 回ずつ |
QueryModeChange / @IsDocBeingEdited | 編集モードか参照モードかで分ける | cfGlobal.editable を条件表示・計算値の条件に使う | WEB フォームにモードの切り替えはありません。参照モードでは入力欄そのものが編集できない状態で表示されます |
@IsNewDoc | 新規作成かどうか | cfGlobal.isNewNote | 「新規作成時に1回だけ」のガードに使います |
入力中(フィールドの式・イベント)
| Notes | WEB フォームでの書き場所 | 補足 |
|---|---|---|
| Default value(固定の初期値) | 初期値(defaultValue) | 固定値はこれで十分 |
| Default value(式)/ Computed when composed | 項目 1 つなら計算値 + cfGlobal.isNewNote かつ「値が空のとき」のガード。複数項目や副作用を伴うならフォームスクリプトの cfAPI.form.onNew(fn) | 初期値に式を書いても、公開した時点の値がフォーム定義に焼き込まれるため、開くたびには評価されません |
| Computed / Computed for display | 計算値(calculateValue) | 表示だけの値は「保存しない(persistent: false)」に |
| Hide-when 式 | 条件表示(簡易な条件、または customConditional) | ロール(cfGlobal)、編集可否、他の項目の値で出し分けられます |
| Input Validation | 検証(validate.custom。valid = true か、エラーメッセージの文字列) | 保存・申請の前に止まります。下書きの間だけ緩くする、といった条件も書けます |
| Input Translation(入力値の整形) | logic(イベント blur または change)の customAction で値を書き換える。既存文書の一括正規化はフォームスクリプトの migrate | 全角→半角、前後の空白の除去など |
| Entering / Exiting | logic(イベント focus / blur) | 入力補助の表示、入力後の補完に |
| OnChange | 他の項目の計算値(自動で再評価される)、または logic(イベント change) | 「A が変わったら B を計算」は、B の計算値に書くだけで足ります |
キーワード式(@DbColumn / @DbLookup) | 選択コンポーネントのデータソース URL(ビュー参照) | 関連記事「選択肢を他の DB・ビューから取り込む」 |
| PostRecalc / F9 | (不要) | 値が変わると依存する式が自動で再評価されます |
ボタンを押したとき
| Notes | WEB フォームでの書き場所 | 補足 |
|---|---|---|
| アクション/ホットスポットの Click | ボタンコンポーネントの action: custom(JavaScript を書く) | data(フォームの値)、form.getComponent('キー')、cfGlobal が使えます |
| 他の処理に「合図」を送る | ボタンの action: event(イベント名を付ける)→ 受け取る側のコンポーネントの logic(trigger: event) | コンポーネント同士を直接参照せずに連携できます |
| 申請・承認ボタンに独自のチェックを挟む | サーバー側: customExtApplyOnClick()/customExtApplyOnClickAfter() ほか(下記) | false を返すと処理を中止できます |
保存・申請・承認のとき
| Notes | 目的 | WEB フォームでの書き場所 | 補足 |
|---|---|---|---|
| QuerySave(入力チェック) | 不備があれば保存させない | 画面側: 必須と検証(validate) | 画面側だけで止まります |
| QuerySave(確定処理の前のチェック) | 条件を満たさなければ申請・承認を止める | サーバー側: customExtApplyOnClick() / customExtApproveOnClick() / customExtSendbackOnClick() / customExtDenyOnClick() / customExtPullbackOnClick() | 戻り値 true で続行、false で中止 |
| QuerySave / PostSave(履歴の記録、項目の書き込み) | 承認者の情報や日時を項目に残す | サーバー側: 保存直前に呼ばれる customExtApplyOnClickAfter() / customExtApproveOnClickAfter() / customExtSendbackOnClickAfter() / customExtDenyOnClickAfter() / customExtPullbackOnClickAfter()(承認・差し戻しなどの全アクションにあります)の中で項目に書く | 例は既存 TIPS「申請部門の最終承認者の ID・漢字名・役職をフィールド保存したい」 |
| PostSave / WebQuerySave(連携、後処理) | 保存後に他システムへ連携、Notes のエージェントを動かす | 外部システム連携(AGENT)の「保存」「下書き保存」トリガ | 既存の LotusScript / Java エージェントを、保存の後に設定だけで呼べます |
| QueryClose | 閉じるときの後始末 | (不要) | ブラウザのタブを閉じるだけです |
典型例 3 つ
以下は考え方を示す例です。コード中のキー名(createdSection など)は例なので、自分のフォームの項目名に置き換えてください。
1. 開いたときにログインユーザーの所属を入れる(PostOpen の置き換え)
フォームスクリプト(キー scriptBlock の非表示 HTML 要素)の本文に、新規作成時のコールバックを登録します。
以下のコードは書き方を示す例です。createdSection と createdBy は例として付けた項目名で、製品が決めた名前ではありません。
自分のフォームに、保存する非表示フィールドとして好きな名前で置いてください。
cfAPI.form.onNew(function (ctx) {
ctx.set('createdSection', cfGlobal.sectionName || '');
ctx.set('createdBy', cfGlobal.currentUserName || '');
});
承認者が開いても値は変わらず、保存して開き直しても作成時の所属が残ります。
項目が 1 つだけなら、その項目の計算値に if (typeof cfGlobal !== 'undefined' && cfGlobal.isNewNote && !value) { value = cfGlobal.sectionName || ''; } と書く従来の方法でもかまいません。
詳しくは関連記事「1回だけ処理を実行する」と「ログインユーザーの氏名・所属・ロールを使う」を参照してください。
2. 条件で編集を抑止する(Hide-when / QueryModeChange の置き換え)
「申請後は金額欄を見せない」「管理者ロール以外には備考欄を出さない」は、対象のコンポーネントの条件表示(customConditional)に書きます。
// 下書きの間(未採番)か、編集できる状態のときだけ表示する
show = (typeof cfGlobal === 'undefined')
|| (cfGlobal.applicationNo === '' && cfGlobal.editable === true);
参照モードでは、もともと入力欄は編集できません。「見せるが触らせない」は条件表示ではなく、参照モードに任せるのが簡単です。
3. 承認時に承認者の情報を項目に書く(QuerySave / PostSave の置き換え)
画面側のロジックは、承認者が参照モードで開くだけでも動きますし、ブラウザで止めることもできます。
「承認のときに必ず 1 回」行う処理は、サーバー側の customExtApproveOnClick() に書きます。
処理の後に return true; で承認を続行し、条件を満たさないときは利用者に知らせて return false; で中止します。
実装例は既存 TIPS「申請部門の最終承認者の ID・漢字名・役職をフィールド保存したい」にあります。
「保存時に 1 回だけ、確実に」はプロコード側で
サーバー側のフックは、プロコード領域の SSJS ライブラリ customLib_SSJS.jss に、決まった名前の関数として書きます。製品本体のコードとは分かれているため、製品を更新しても上書きされません。
| 分類 | 関数名 | 呼ばれるとき |
|---|---|---|
| 初期化 | customInitApp() | アプリの読み込み時に 1 回 |
| フォームの表示 | customFormBeforePageLoad() / customFormAfterPageLoad() | フォームの表示前/表示後 |
customFormAfterRestoreView() / customFormBeforeRenderResponse() / customFormAfterRenderResponse() | 画面の復元・描画の前後(部分更新のたびに呼ばれる点に注意) | |
| アクションボタン | customExtApplyOnClick()(申請)/ customExtApproveOnClick()(承認)/ customExtSendbackOnClick()(差し戻し)/ customExtDenyOnClick()(否認)/ customExtPullbackOnClick()(引き戻し) | 各ボタンを押したとき、承認コメントのダイアログが表示される前。true で続行、false で中止 |
customExtApplyOnClickAfter() / customExtApproveOnClickAfter() / customExtSendbackOnClickAfter() / customExtDenyOnClickAfter() / customExtPullbackOnClickAfter() | 各ボタンの処理で、保存の直前 |
どのアクションにも、末尾に After が付かないフック(OnClick)と付くフック(OnClickAfter)の 2 つがあります。使い分けは次のとおりです。
OnClick(customExtApplyOnClick()など): 承認コメントのダイアログが表示される前に呼ばれます。入力チェックなど、条件を満たさないときに処理を止める用途に使いますOnClickAfter(customExtApplyOnClickAfter()、customExtApproveOnClickAfter()、customExtSendbackOnClickAfter()、customExtDenyOnClickAfter()、customExtPullbackOnClickAfter()): 保存の直前に呼ばれます。項目への書き込みなど、保存直前の処理に使います
「保存」「下書き保存」の直後に動かしたい処理が Notes のエージェントとして既にあるなら、プロコードを書かずに、外部システム連携(AGENT)の「保存」「下書き保存」トリガで呼び出せます。
結果の確認
- 開いたときの処理: フォームを開き直しても、入力欄に何か打っても、値が意図したタイミングでしか変わらないこと
- 条件表示: 下書き・申請後・承認者の参照モードの 3 つの状態で開き、見え方が意図どおりであること
- サーバー側のフック: 条件を満たさない文書で申請・承認を行い、中止のメッセージが出て状態が進まないこと
補足・注意
- フォームビルダーのプレビューでは
cfGlobalが未定義です。式の先頭でtypeof cfGlobal !== 'undefined'を確かめてください - 部分更新(Ajax)が起きると WEB フォームが再描画され、
initializedなどのイベントも再び起きます。「1 回だけ」にしたい処理は、フォームスクリプトのonOpen/onNew/migrateに書けば再実行されません(logic や計算値に書く場合はガードが必要です) - フォームビルダーのイベント名(
initialized、change、blur、focus、renderなど)と、logic で使える変数は、既存記事「consentFlow フォームビルダー ライフサイクルイベント一覧」にまとまっています