モデル駆動型アプリのフォーム OnSave イベント (クライアント API 参照)

モデル駆動型アプリのフォーム OnSave イベントを使用すると、レコードを保存する前に、ロジックの実行、データの検証、保存の取り消しを行うことができます。 OnSave イベントは、次のタイミングで発生します。

  • ユーザーは、保存する変更されたデータがない場合でも、コマンド バーの [ 保存 ] または [ 更新 ] ボタンを選択します。
  • コードは、保存する変更されたデータがない場合でも、 formContext.data.entity.save メソッドを実行します。
  • ユーザーがフォームから移動し、フォームに保存されていないデータがあります。
  • 自動保存オプションが有効で、データ変更の 30 秒後にフォームに保存されていないデータがあります。
  • コードが formContext.data.save メソッドを実行し、フォームに保存されていないデータがあります。
  • コードが formContext.data.refresh メソッドを実行して true 値を最初のパラメーターとして渡し、フォームに保存されていないデータがあります。

ヒント

予定、定期的な予定、またはサービス アクティビティ レコードのOnSave イベントは保存操作を取り消し、CreateまたはUpdateの代わりにBook メッセージを使用して変更を保存します。 この動作のため、これらのテーブルの OnSave イベント ハンドラーと PostSave イベント ハンドラーは機能しません。

保存を実行するのにクリックされるボタンを確認するには、getSaveMode メソッドを使用します。

イベント引数オブジェクト内で preventDefault メソッドを使用して、保存アクションを取り消すことができます。 preventDefault メソッドには、実行コンテキストの一部である getEventArgs メソッドを使用してアクセスできます。 実行コンテキストは自動的にフォーム イベント ハンドラーに渡されます。

非同期イベント ハンドラー サポート

OnSave イベントには、イベント ハンドラーによって返される promise が解決するのを待ってから保存する機能があり、OnSave イベントを非同期 (「非同期」) にすることができます。

OnSave イベント ハンドラーがプロミスを返すと、OnSave イベントは非同期になります。 レコードの保存は、ハンドラーによって返された各プロミスが解決されたときに行われます。 返されるすべてのプロミスについて、各プロミス には 10 秒の制限があり、その後、プラットフォームはプロミスがタイムアウトしたと見なします。このタイムアウトは、プロミスごとに適用されます。 たとえば、5 つの promise が返された場合、合計待機時間は 50 秒です。

promise が拒否された、またはタイムアウトした場合、保存操作は引き続き現在のスクリプト エラーと同様に動作します。 スクリプト エラーまたは拒否された promise がある、またはハンドラーがタイム アウトした場合に保存イベントを発生させないようにするには、その特定のハンドラーのイベント引数オブジェクトの中で preventDefault メソッドを使用します。

イベント引数オブジェクト内の preventDefault メソッドを使用することで、ハンドラーのエラーであるかどうかに関係なく、保存操作をキャンセルすることもできます。  このメソッドが呼び出された場合、非同期 OnSave イベントはすべての promise が解決するまで待機しますが、保存は行われません。 このメソッドを呼び出すことは、.then() & .catch() 内のロジックがまだ実行されていることを意味します。

OnSave イベントは、ハンドラーごとに返される 1 つの promise を待機します。 複数の promise が必要な場合は、すべての promise を Promise.all() メソッドでラップして、結果として得られる単一の promise を返すことをお勧めします。 すべてが promise を返す複数のハンドラーでは、すべてのイベントを呼び出して、必要なすべての promise をラップする単一の promise を返す 1 つのハンドラーを作成することをお勧めします。 これによって、タイムアウトによる待機時間を最小限に抑えることができます。

例: 非同期 OnSave ハンドラーを使用する場合

選択した顧客資産が作業指示書に表示されているのと同じアカウントを持っていることを検証する必要がある作業指示サービス タスクを作成することを検討してください。 作業指示書と顧客資産のアカウントのフェッチはどちらも非同期プロセスであり、検証する前に両方を完了する必要があります。

このシナリオでは、複数の非同期プロセスがあり、両方の呼び出しが 1 つの Promise を返すので、両方を Promise.all() メソッドでラップします。

ヒント

preventDefault メソッドは同期的にのみ使用できます。

例:

 function myHandler() {
    return Promise.all([getWorkOrderPromise, getCustomerAssetPromise]).then((values) => {
        var workOrder = values[0];
        var customerAsset = values[1];
        // Perform validation
        if (isValid(workOrder, customerAsset)) {
            return Promise.resolve();
        }
        return Promise.reject(new Error("Validation failed for the work order and customer asset"));
   });
 }

アプリ設定を使用して非同期 OnSave ハンドラーを有効にする

async onSave ハンドラーを使用するには、アプリ設定を使用して機能を有効にします。

  1. https://make.powerapps.com に移動します。

  2. 適切な環境を選択してください。

  3. 左側のナビゲーション ウィンドウから、アプリ を選択します。

  4. アプリを選択し、[ ... ] (省略記号) を選択し、[ 編集] を選択します。

  5. コマンド バーから 設定 を選択します。

  6. ダイアログが開いたら、機能 を選択します。

  7. 非同期 onSave ハンドラー を有効化します。

  8. 保存 を選択します。

    アプリの [設定] ダイアログで有効になっている Async onSave ハンドラー機能の設定のスクリーンショット。

非同期 OnSave ハンドラーのタイムアウトを無効にする

非同期 OnSave ハンドラーを使用する場合、フォームはハンドラーから返されるプロミスが実行されるのを待機します。 フォームの保存が適切なタイミングで完了するように、ハンドラーは 10 秒後にタイムアウト例外をスローし、非同期 OnSave ハンドラーをチューニングしてパフォーマンスを向上させます。

OnSave ハンドラーを 10 秒より長く一時停止する必要があるシナリオがあります。 例えば、ダイアログを開き、ユーザーの入力を待ってから保存を続行するような場合です。 非同期操作が promise の解決を待機するようにするには、 disableAsyncTimeout メソッドを使用します。

ヒント

await ステートメントまたは非同期呼び出しの前に、disableAsyncTimeout を呼び出す必要があります。

例:

async function myHandler(context) {  
     context.getEventArgs().disableAsyncTimeout();
     // The 10000ms time out will not be disabled if the above line does not come before all async awaits
     await Xrm.Navigation.openConfirmDialog({ text: "Are you sure you want to save?" });
 }

disableAsyncTimeout を呼び出すと、そのハンドラーのタイムアウトは適用されません。 当該ハンドラーのプロミスが実行されるのを待機します。

このパターンは、フォーム保存のパフォーマンスに影響する可能性があります。

グリッド OnSave イベント
イベント (クライアント API 参照)
モデル駆動型アプリのフォームとグリッド内のイベント