web-dev-qa-db-ja.com

Xrm.Pageの削除後のフォームでホストされているWebResourceからコンテキストからアクセスする

フォームでホストされているWebResourceからフォームのFormContextにアクセスするための最良の方法は何ですか?

ドキュメントは html WebResourceからフォームコンテキストにアクセスして、parent.Xrm.Pageを使用する と言います。

フォームに追加されたHTML Webリソースは、フォームに読み込まれたJavaScriptライブラリによって定義されたグローバルオブジェクトを使用できません。 HTML Webリソースは、parent.Xrm.Pageまたはparent.Xrm.Utilityを使用してフォーム内のXrm.PageまたはXrm.Utilityオブジェクトと相互作用する場合がありますが、フォームスクリプトによって定義されたグローバルオブジェクトは、親を使用してアクセスできません。フォームに読み込まれたスクリプトに依存しないように、HTML Webリソース内でHTML Webリソースに必要なすべてのライブラリを読み込む必要があります。

ただし、Xrm.Pageは非推奨であり、削除されます。その場合、私の想定はparent.Xrm.Pageもその時点では機能しません。

この仮定は、ドキュメントページの最後に投稿されたクローズされた問題によってエコーされます。

フォームに追加されたHTML Webリソースは、読み込まれたJavaScriptライブラリによって定義されたグローバルオブジェクトを使用できませんが、上のページの問題を見ると、誰かが明白な質問をします:機能のギャップを防ぐために、HTMLはどのようにエンティティフォームに含まれているWebリソースは、フォームのコンテキストにアクセスします。 Xrm.Pageが削除されるまでに、「parent.Xrm.Page」のサポートされている代替手段があるかどうかに依存できますか?

返信先は getContentWindow を使用し、フォームのオンロードから挿入します。この値を受け入れることができるようにWebリソースが時間内にロードを完了する保証はないので、これはまだ素晴らしいことではありません。開発者はそのようにコメントし、getContentWindow docページに作業を投稿しました

function form_onload(executionContext) {
    const formContext = executionContext.getFormContext();
    const wrControl = formContext.getControl("new_myWebResource.htm");
    if (wrControl) {
        wrControl.getContentWindow().then(contentWindow => {
            let numberOfCalls = 0;
            let interval = setInterval(() => {
                if (typeof contentWindow.setClientApiContext !== "undefined") {
                    clearInterval(interval);
                    contentWindow.setClientApiContext(Xrm, formContext);
                }
                else
                    //stop interval after 1 minute
                    if (++numberOfCalls > 600) {
                         clearInterval(interval);
                         throw new Error("Content Window failed to initialize.");
                    }
            }, 100);
        });
    }
}

これは現在、これを機能させるための最良/推奨されるアプローチですか、それともXrm.Pageが削除された場合でもparent.Xrm.Pageは機能しますか?

2
Daryl

しばらくgetContentWindowを使用していますが、Webリソースが読み込まれるのを待ちます。

この関数がバックエンドで行うことは、iframeからコンテンツを取得することです。そのため、これはcontentWindowがロードされるのを待つと強く信じています。私の考えでは、このcontentWindowはIframeの一般的なcontentWindowとまったく同じように動作します。 https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/contentWindow

例として、2つのタブがある場合を考えてみましょう:一般と詳細。

OnLoadにgetContentWindowがあり、Webリソースが[詳細]タブにある場合、getContentWindowは[詳細]タブがクリックされたときにのみ読み込まれるため、Webリソースがレンダリングされます。

function form_onload(executionContext) {
  const formContext = executionContext.getFormContext();
  const wrControl = formContext.getControl("new_myWebResource.htm");
  if (wrControl) {
    var contentWindow = await wrControl.getContentWindow();
    contentWindow.CallTheFunctionInYourWebResource(Xrm,formContext,...params)
  }
}

あなたのウェブリソースには次のようなものがあります:

<html>...
<script>
function CallTheFunctionInYourWebResource(_xrm, _formContext) {
  // Do whatever you need to do here
}

</script>

それが役に立てば幸い!

1
Victor Sanchez