Dynamics CRM 2011 Xrm.Page サンプルライブラリ紹介 その 1

みなさん、こんにちは。

今週は The Microsoft Conference 2011 ウィークですが、参加された方は
Windows Phone 当たったでしょうか?? Windows 8 の Developer Preview
も公開され、色々と試せることが山盛りですが、Dynamics CRM も負けずに
情報を公開してきます!

今回から数回にわたり Dynamics CRM 2011 で刷新されたクライアントサイド
スクリプトのサンプルを紹介していきます。概要はこちらの記事をご覧ください。

Xrm.Page Sample Libraries サンプル

Xrm.Page 関連のサンプルは 1 つのソリューション形式で提供されます。 このソリューションをインポートすることで、JScript Web リソースが 登録されます。また実際にスクリプトを呼び出すためのリボンが含まれています。

次回以降でも必要なものですので、``登録手順を紹介します。

サンプルソリューション登録方法

1. Internet Explorer で Dynamics CRM 2011 に接続します。

2. 設定 | カスタマイズ | ソリューションをクリックします。

3. インポートをクリックして、参照ボタンをクリックします。

4. sdk\samplecode\js\formscripts\formscriptdemonstrations_1_0_0_0_managed.zip を選択します。ウィザードを完了します。警告は無視して結構です。

サンプル関数の利用方法

次にサンプルの関数を利用する方法です。今回は取引先企業の フォームで検証してみます。

1. ワークプレース | 取引先企業をクリックします。

2. 新規ボタンをクリックして、レコードの新規作成画面を開きます。

3. カスタマイズタブをクリックして、カスタムボタンを確認します。

image

4. カスタムボタンをクリックして、SDK.ControlSamples.js をクリックします。

image

5. ここでは setFocusDemo をクリックしてみます。

6. 以下のような画面が開くので、フォーカスを当てたいフィールドをクリックします。
ここでは FAX をクリックしてみました。

image

7. 元のフォーム上で FAX にカーソルがあることを確認します。

image

サンプルの解説

今回は画面上での変化がわかりやすいコントロール系の操作サンプルを
まず 1 つ紹介します。サンプルファイルは以下のフォルダにあります。

SDK\SampleCode\JS\FormScripts\SDK.ControlSamples.js

また上記手順の SDK.ControlSamples.js メニュー内にあるものが 全てここに記述されています。SDK.ControlSamples.js のサンプルは Xrm.Page.ui で取得できる control オブジェクトで利用できるメソッド のサンプルです。全べのメソッドは SDK「Xrm.Page.ui control methods」 を参照してください。

名前空間の利用

サンプルスクリプトでは名前空間を利用しています。これにより関数名の重複を
避けることが可能です。

名前空間の最上位は SDK で、その下に ControlSamples が定義されているため
例えば addCustomView 関数を呼ぶためには、 SDK.ControlSamples.addCustomView
と記述する必要があります。

[名前空間定義部分]
//SDK というオブジェクトが無い場合には、作成する。 
if (typeof (SDK) == "undefined") { SDK = {}; }
// SDK 配下に ControlSamples を定義し、中にサンプル関数を含める。
SDK.ControlSamples = {

<中略 : 関数が登録されています>

// サンプル関数の終わり 
};

addCustomView サンプル関数

controlObj.addCustomView のサンプルです。 addCustomView は参照型の
コントロールに、カスタムのビューを追加することが可能です。

例えば取引先企業のフォームには、取引先企業の親会社フィールドがあり
参照型コントロールとなっています。

image

検索をアイコンをクリックすると 「レコードの検索」 画面が表示されます。
既定で複数のビューが選択可能ですが、このビューの選択肢として
addCustomView  を利用して、カスタムビューを動的に埋め込めます。

サンプルコード解説

サンプルコードに直接コメントを入れて解説していきます。尚 addCustomView
サンプルは Xrm.Page サンプルスクリプトの中で最も難解です。以下に簡単な
フローを記述しておきます。

前提: 参照型のコントロールに対して、検索対象が取引先企業のものに、
カスタムの取引先企業検索ビューを埋め込みます。

1. フォーム上の全コントロールを確認して、参照型のものを取得する。
2. 参照型コントロールの既定のビューの GUID を取得する。
3. REST エンドポイントを利用して、既定のビューの中身を取得する。
4. 既定のビューの検索対象が取引先企業か確認する。
5. 取引先企業の場合にはカスタムビューを埋め込む。

では実際のスクリプトを確認します。

[addCustomView 関数]
一番初めに呼び出される関数です。

addCustomView: function () {
      // カスタムビューの GUID です。一意のものであれば任意 。
      var viewId = "{C7034F4F-6F92-4DD7-BD9D-9B9C1E996380}";
      // 検索対象のエンティティ名。 取引先企業を指定。
      var entityName = "account";
      // カスタムビューの名前。この名前がレコードの検索で表示される。 
      var viewDisplayName = "SDK Sample View";
      // ビューで利用するレコード検索用の FetchXML 。
      var fetchXml = "<fetch version='1.0' " +
            "output-format='xml-platform' " +
            "mapping='logical'>" +
      "<entity name='account'>" +
      "<attribute name='name' />" +
      "<attribute name='address1_city' />" +
      "<order attribute='name' " +
            "descending='false' />" +
      "<filter type='and'>" +
            "<condition attribute='ownerid' " +
                                  "operator='eq-userid' />" +
            "<condition attribute='statecode' " +
                                  "operator='eq' " +
                                  "value='0' />" +
            "</filter>" +
            "<attribute name='primarycontactid' />" +
            "<attribute name='telephone1' />" +
            "<attribute name='accountid' />" +
            "<link-entity alias='accountprimarycontactidcontactcontactid' " +
                                  "name='contact' " + 
                                  "from='contactid' " +
                                  "to='primarycontactid' " +
                                  "link-type='outer' " +
                                  "visible='false'>" +
                                  "<attribute name='emailaddress1' />" +
            "</link-entity>" +
            "</entity>" +
      "</fetch>";
     
      // ビューの列を設定。
      var layoutXml = "<grid name='resultset' " +
            "object='1' " +
            "jump='name' " +
            "select='1' " +
            "icon='1' " +
            "preview='1'>" +
      "<row name='result' " +
            "id='accountid'>" +
      "<cell name='name' " +
            "width='300' />" +
      "<cell name='telephone1' " +
            "width='100' />" +
      "<cell name='address1_city' " +
            "width='100' />" +
      "<cell name='primarycontactid' " +
            "width='150' />" +
      "<cell name='accountprimarycontactidcontactcontactid.emailaddress1' " +
            "width='150' " +
      "disableSorting='1' />" +
      "</row>" +
      "</grid>"; 

      var lookupsModified = [];
      // isLookup カスタム関数と Xrm.Page.ui.controls.get を利用して、フォーム上の
      // コントロールから参照コントロールを全て取得する。
      var lookupControls = Xrm.Page.ui.controls.get(SDK.ControlSamples.isLookup);

      // 取得した参照コントロールを順番に確認。
      for (var i in lookupControls) 
      { 
            // processLookup 関数に作成したビューの情報等を渡す。
            SDK.ControlSamples.processLookup(lookupControls[i], viewId, entityName, viewDisplayName, fetchXml, layoutXml);
      }
},

[isLookup 関数]
コントロールが参照型か確認する関数です。

isLookup: function (control, index) {
      // コントロールが lookup 型か確認する。
      return control.getControlType() == "lookup";
},

[processLookup 関数]
参照型のコントロールに対して、既定のビューの詳細を REST から取得します。

processLookup: function (lookupControl, viewId, entityName, viewDisplayName,
                                              fetchXml, layoutXml) {
      // 参照コントロールの既定のビューの GUID を取得。
      var currentDefaultViewId = lookupControl.getDefaultView();

      // このサンプルでは account エンティティのカスタムビューを追加するので、
      // 既定のビューが account エンティティのビューであるか確認する必要がある。
      // 以下で REST エンドポイントを利用して既定のビューの定義を取得し、対象エンティティを確認

      // REST エンドポイント利用の準備。
      var oReq = SDK.ControlSamples.getXMLHttpRequest(); 
      // REST エンドポイントの URL 作成。ビュー定義を取るので SavedQuerySet を利用。
      if (oReq != null) { var url = Xrm.Page.context.getServerUrl() + "/XRMServices/2011/OrganizationData.svc/SavedQuerySet(guid'" + currentDefaultViewId + "')";
      oReq.url = url; oReq.open("GET", url, true);
      // コールバック関数として、続きを処理する changeLookupDefaultView を指定。
      oReq.onreadystatechange = function () { SDK.ControlSamples.changeLookupDefaultView(oReq, lookupControl, viewId, entityName, viewDisplayName, fetchXml, layoutXml); };
      oReq.send();
      }
},

[getXMLHttpRequest 関数]
XMLHttpRequest オブジェクトを作成します。

getXMLHttpRequest: function () {
      // XMLHttpRequest オブジェクトの準備。
      if (window.XMLHttpRequest) { return new window.XMLHttpRequest; }
      else {
            try { return new ActiveXObject("MSXML2.XMLHTTP.3.0"); }
            catch (ex) { return null; }
      }
},

[changeLookupDefaultView 関数]
既定のビューが取引先企業であった場合に、カスタムビューを埋め込みます。

changeLookupDefaultView: function (oReq, lookupControl, viewId, 
                                                                    entityName, viewDisplayName, fetchXml, layoutXml) {
      // REST エンドポイントから返ったデータを確認。
      if (oReq.readyState == 4 /* complete */) {
            if (oReq.status == 200) {
                  // 返ったデータを XML として保存。
                  xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
                  xmlDoc.async = false; 
                  xmlDoc.loadXML(oReq.responseText);
                  // 既定のビューの検索対象を保存した XML から確認。
                  var returnedTypeCodeNode = xmlDoc.selectSingleNode("//d:ReturnedTypeCode");
                  if (returnedTypeCodeNode) {
                        var entityName = returnedTypeCodeNode.text;
                        // 既定のビューの検索対象が Account の場合
                        if (entityName == "account") {
                              // addCustomView メソッドで、カスタムビューを埋め込む。
                              lookupControl.addCustomView(viewId, entityName, viewDisplayName, fetchXml, layoutXml, false);
                              // setDefaultView メソッドで埋め込んだビューを既定に設定。
                              lookupControl.setDefaultView(viewId); 
                              // 処理が完了したことを画面に通知。
                              alert("The lookup control for the '" +
                                        lookupControl.getName() +
                                        "' attribute was updated with a new default view.\n\nThe new view id is '" +
                                        lookupControl.getDefaultView() + "'.");
                        } 
                   } 
             } 
       }
},

動作確認

1. 取引先企業のフォームを開き、カスタマイズタブをクリックします。

2. SDK.ControlSamples.js より addCustomView をクリック。しばらく待ちます。

image

3. メッセージが出たら OK をクリック。

image

4. 取引先企業の親会社で、検索アイコンをクリック。

image

5. ビューとして SDK Sample View が指定されていることを確認。

image

6. 取引先責任者で、検索アイコンをクリック。

7. 検索対象が取引先企業ではないため、カスタムビューが追加されていない
ことを確認します。

image

まとめ

今回のサンプルではどのようなフォームでも機能するように、フォーム上の
全てのコントロールを取得したり、既定のビューのタイプを REST を利用して
取得したりと、かなり遠回りな実装をしています。

実際の環境では、既にカスタムビューを埋め込みたいコントロールは
特定できていると思いますので、よりシンプルにコードが記述できるはずです。

次回は他のコントロール系のサンプルを紹介します。

‐ Dynamics CRM サポート 中村 憲一郎