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

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 ハンドラーを使用する場合のシナリオ例

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

このシナリオでは、複数の非同期プロセスがあるため、Promise.all() メソッドで両方をラップすることにより両方の呼び出しが単一の promise を返します。

注意

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

例:

 function myHandler(context) {
    return new Promise((resolve) => {
       setTimeout( () => {
          context.getEventArgs().preventDefault();
       }, 1000);
   });
 }

アプリ設定を使用して非同期 OnSave を有効にする

非同期 onSave ハンドラーを使用するには、アプリの設定で有効にする必要があります:

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

  2. 正しい環境を選択するようにしてください。

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

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

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

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

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

  8. 保存 を選択します。

    非同期 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 イベント

注意

ドキュメントの言語設定についてお聞かせください。 簡単な調査を行います。 (この調査は英語です)

この調査には約 7 分かかります。 個人データは収集されません (プライバシー ステートメント)。