サンプル: 依存オプション セット (候補リスト) の作成
公開日: 2016年11月
対象: Dynamics CRM 2015
あるオプション セット フィールドの値を、別のオプション セット フィールドで選択された値によってフィルター処理するという一般的な要件があります。 このトピックでは、再利用可能な JScript ライブラリ、フォーム イベント、および XML Web リソースを使用して、これを実現する 1 つの方法を説明します。
このサンプルの機能を監視および確認するために、SDK のダウンロードの場所 DependentOptionSetsSample_1_0_0_2_managed.zip から SDK\SampleCode\JS\FormScripts 管理ソリューションをインストールできます。
Microsoft Dynamics CRM SDK パッケージをダウンロードします。
この解決方法の目標
この解決方法の目的は次の要件を満たすことです。
オプション セット フィールドの任意のペアに対して使用できる、汎用の再利用可能 JScript ライブラリを提供します。
依存オプション セット フィールドの連鎖に対応できます。 各依存オプション セット フィールドのオプションは、別のフィールドの値に基づいてフィルター処理されるため、さらに他のオプション セット フィールドのオプションが、最初の依存オプション セット フィールドで選択されたオプションによってフィルター処理される可能性があります。 階層的な依存関係がある一連のオプション セット フィールドに対応できます。
依存オプションのフィルター処理は、XML Web リソースで設定されます。 こうすることで、コードを変更せずにオプションのマッピングを変更できます。XML Web リソースの編集は、開発者以外でもオプションの構成を容易に行うことができ、コードを破損する可能性が高くありません。
この解決方法では複数の言語がサポートされます。 フィルター処理は、オプションのテキストではなくデータ値のみに基づきます。
フィルター処理は、フォームにおける 1 つの属性コントロールのいくつのインスタンスに対しても機能します。
例
このセクションでは、この方法の 1 つの適用例とサンプル ライブラリの適用手順について説明します。
Ticket (sample_ticket) エンティティ フォームには、製品を分類するための 3 つのオプション セット フィールドとオプションがあります。 以下の表に、オプション セットのオプションで必要なフィルター処理を示します。
カテゴリ (sample_category) |
サブ カテゴリ (sample_subcategory) |
種類 (sample_type) |
---|---|---|
値:727000000 ラベル: ソフトウェア |
値:727000000 ラベル: 個人生産性 |
値:727000000 ラベル: ワード プロセッサ |
値:727000001 ラベル: スプレッドシート |
||
値:727000002 ラベル: インターネット ブラウザ |
||
値:727000003 ラベル: 電子メール |
||
値:727000001 ラベル: ビジネス アプリケーション |
値:727000004 ラベル: 顧客間関係管理 |
|
値:727000005 ラベル: エンタープライズ リソース管理 |
||
値:727000006 ラベル: 人事管理 |
||
値:727000002 ラベル: オペレーティング システム |
値:727000007 ラベル: Windows Vista |
|
値:727000008 ラベル: Windows 7 |
||
値:727000009 ラベル: Windows Server 2003 |
||
値:727000010 ラベル: Windows Server 2008 |
||
値:727000001 ラベル: ハードウェア |
値:727000003 ラベル: デスクトップ コンピューター |
値:727000011 ラベル: Workstation x1000 |
値:727000012 ラベル: Workstation x2000 |
||
値:727000013 ラベル: Workstation x3000 |
||
値:727000014 ラベル: ワークステーション x4000 |
||
値:727000004 ラベル: ラップトップ コンピューター |
値:727000015 ラベル: ラップトップ 1000 シリーズ |
|
値:727000016 ラベル: ラップトップ 2000 シリーズ |
||
値:727000017 ラベル: ラップトップ 3000シリーズ |
||
値:727000018 ラベル: ラップトップ 4000シリーズ |
||
値:727000005 ラベル: モニタ |
値:727000019 ラベル: CRT-XYZ 17 インチ |
|
値:727000020 ラベル: LCD-XYZ 17 インチ |
||
値:727000021 ラベル: LCD-XYZ 21 インチ |
||
値:727000022 ラベル: LCD-XYZ 24 インチ |
||
値:727000006 ラベル: プリンター |
値: 727000023 ラベル: Series 1000 Printer - Private |
|
値: 727000024 ラベル: Series 2000 プリンター - 個人用 |
||
値:727000025 ラベル: Series 9000 プリンター - 個人用 |
||
値:727000026 ラベル: Series 9000 カラー プリンター - 共用 |
||
値:727000007 ラベル: 電話 |
値:727000027 ラベル: 公衆電話 |
|
値:727000028 ラベル: IP 電話 |
||
値:727000029 ラベル: モバイル電話 |
フィルター処理を有効にする
オプションの必要なフィルター処理を次の XML ドキュメントに変換し、sample_TicketDependentOptionSetConfig.xml という名前の XML Web リソースとしてアップロードします。 ラベル値は、ドキュメントを編集しやすくするために含まれていますが、オプションをフィルター処理するスクリプトでは使用されません。
<DependentOptionSetConfig entity="sample_ticket" > <ParentField id="sample_category" label="Category"> <DependentField id="sample_subcategory" label="Sub Category" /> <Option value="727000000" label="Software"> <ShowOption value="727000000" label="Personal Productivity" /> <ShowOption value="727000001" label="Business Applications" /> <ShowOption value="727000002" label="Operating Systems" /> </Option> <Option value="727000001" label="Hardware"> <ShowOption value="727000003" label="Desktop Computer" /> <ShowOption value="727000004" label="Laptop Computer" /> <ShowOption value="727000005" label="Monitor" /> <ShowOption value="727000006" label="Printer" /> <ShowOption value="727000007" label="Telephone" /> </Option> </ParentField> <ParentField id="sample_subcategory" label="Sub Category"> <DependentField id="sample_type" label="Type" /> <Option value="727000000" label="Personal Productivity"> <ShowOption value="727000000" label="Word Processor" /> <ShowOption value="727000001" label="Spreadsheet" /> <ShowOption value="727000002" label="Internet Browser" /> <ShowOption value="727000003" label="E-mail" /> </Option> <Option value="727000001" label="Business Applications"> <ShowOption value="727000004" label="Customer Relationship Management" /> <ShowOption value="727000005" label="Enterprise Resource Management" /> <ShowOption value="727000006" label="Human Resource Managment" /> </Option> <Option value="727000002" label="Operating Systems"> <ShowOption value="727000007" label="Windows Vista" /> <ShowOption value="727000008" label="Windows 7" /> <ShowOption value="727000009" label="Windows Server 2003" /> <ShowOption value="727000010" label="Windows Server 2008" /> </Option> <Option value="727000003" label="Desktop Computer"> <ShowOption value="727000011" label="Workstation x1000" /> <ShowOption value="727000012" label="Workstation x2000" /> <ShowOption value="727000013" label="Workstation x3000" /> <ShowOption value="727000014" label="Workstation x4000" /> </Option> <Option value="727000004" label="Laptop Computer"> <ShowOption value="727000015" label="Laptop 1000 series" /> <ShowOption value="727000016" label="Laptop 2000 series" /> <ShowOption value="727000017" label="Laptop 3000 series" /> <ShowOption value="727000018" label="Laptop 4000 series" /> </Option> <Option value="727000005" label="Monitor"> <ShowOption value="727000019" label="CRT-XYZ 17 inch" /> <ShowOption value="727000020" label="LCD-XYZ 17 inch" /> <ShowOption value="727000021" label="LCD-XYZ 21 inch" /> <ShowOption value="727000022" label="LCD-XYZ 24 inch" /> </Option> <Option value="727000006" label="Printer"> <ShowOption value="727000023" label="Series 1000 Printer - Private" /> <ShowOption value="727000024" label="Series 2000 Color Printer - Private" /> <ShowOption value="727000025" label="Series 9000 Printer - Shared" /> <ShowOption value="727000026" label="Series 9000 Color Printer - Shared" /> </Option> <Option value="727000007" label="Telephone"> <ShowOption value="727000027" label="PSTN Phone" /> <ShowOption value="727000028" label="IP Phone" /> <ShowOption value="727000029" label="Mobile Phone" /> </Option> </ParentField> </DependentOptionSetConfig>
次のコードを使用して、sample_SDK.DependentOptionSetSample.js という名前の JScript Web リソースを作成します。
//If the SDK namespace object is not defined, create it. if (typeof (SDK) == "undefined") { SDK = {}; } // Create Namespace container for functions in this library; SDK.DependentOptionSet = {}; SDK.DependentOptionSet.init = function (webResourceName) { //Retrieve the XML Web Resource specified by the parameter passed var clientURL = Xrm.Page.context.getClientUrl(); var pathToWR = clientURL + "/WebResources/" + webResourceName; var xhr = new XMLHttpRequest(); xhr.open("GET", pathToWR, true); xhr.setRequestHeader("Content-Type", "text/xml"); xhr.onreadystatechange = function () { SDK.DependentOptionSet.completeInitialization(xhr); }; xhr.send(); }; SDK.DependentOptionSet.completeInitialization = function (xhr) { if (xhr.readyState == 4 /* complete */) { if (xhr.status == 200) { xhr.onreadystatechange = null; //avoids memory leaks var JSConfig = []; var ParentFields = xhr.responseXML.documentElement.getElementsByTagName("ParentField"); for (var i = 0; i < ParentFields.length; i++) { var ParentField = ParentFields[i]; var mapping = {}; mapping.parent = ParentField.getAttribute("id"); mapping.dependent = SDK.Util.selectSingleNode(ParentField, "DependentField").getAttribute("id"); mapping.options = []; var options = SDK.Util.selectNodes(ParentField, "Option"); for (var a = 0; a < options.length; a++) { var option = {}; option.value = options[a].getAttribute("value"); option.showOptions = []; var optionsToShow = SDK.Util.selectNodes(options[a], "ShowOption"); for (var b = 0; b < optionsToShow.length; b++) { var optionToShow = {}; optionToShow.value = optionsToShow[b].getAttribute("value"); optionToShow.text = optionsToShow[b].getAttribute("label"); option.showOptions.push(optionToShow); } mapping.options.push(option); } JSConfig.push(mapping); } //Attach the configuration object to DependentOptionSet //so it will be available for the OnChange events SDK.DependentOptionSet.config = JSConfig; //Fire the onchange event for the mapped optionset fields // so that the dependent fields are filtered for the current values. for (var depOptionSet in SDK.DependentOptionSet.config) { var parent = SDK.DependentOptionSet.config[depOptionSet].parent; Xrm.Page.data.entity.attributes.get(parent).fireOnChange(); } } } }; // This is the function set on the onchange event for // parent fields SDK.DependentOptionSet.filterDependentField = function (parentField, childField) { for (var depOptionSet in SDK.DependentOptionSet.config) { var DependentOptionSet = SDK.DependentOptionSet.config[depOptionSet]; /* Match the parameters to the correct dependent optionset mapping*/ if ((DependentOptionSet.parent == parentField) && (DependentOptionSet.dependent == childField)) { /* Get references to the related fields*/ var ParentField = Xrm.Page.data.entity.attributes.get(parentField); var ChildField = Xrm.Page.data.entity.attributes.get(childField); /* Capture the current value of the child field*/ var CurrentChildFieldValue = ChildField.getValue(); /* If the parent field is null the Child field can be set to null */ if (ParentField.getValue() == null) { ChildField.setValue(null); ChildField.setSubmitMode("always"); ChildField.fireOnChange(); // Any attribute may have any number of controls // So disable each instance var controls = ChildField.controls.get() for (var ctrl in controls) { controls[ctrl].setDisabled(true); } return; } for (var os in DependentOptionSet.options) { var Options = DependentOptionSet.options[os]; var optionsToShow = Options.showOptions; /* Find the Options that corresponds to the value of the parent field. */ if (ParentField.getValue() == Options.value) { var controls = ChildField.controls.get(); /*Enable the field and set the options*/ for (var ctrl in controls) { controls[ctrl].setDisabled(false); controls[ctrl].clearOptions(); for (var option in optionsToShow) { controls[ctrl].addOption(optionsToShow[option]); } } /*Check whether the current value is valid*/ var bCurrentValueIsValid = false; var ChildFieldOptions = optionsToShow; for (var validOptionIndex in ChildFieldOptions) { var OptionDataValue = ChildFieldOptions[validOptionIndex].value; if (CurrentChildFieldValue == OptionDataValue) { bCurrentValueIsValid = true; break; } } /* If the value is valid, set it. If not, set the child field to null */ if (bCurrentValueIsValid) { ChildField.setValue(CurrentChildFieldValue); } else { ChildField.setValue(null); } ChildField.setSubmitMode("always"); ChildField.fireOnChange(); break; } } } } }; SDK.Util = {}; //Helper methods to merge differences between browsers for this sample SDK.Util.selectSingleNode = function (node, elementName) { if (typeof (node.selectSingleNode) != "undefined") { return node.selectSingleNode(elementName); } else { return node.getElementsByTagName(elementName)[0]; } }; SDK.Util.selectNodes = function (node, elementName) { if (typeof (node.selectNodes) != "undefined") { return node.selectNodes(elementName); } else { return node.getElementsByTagName(elementName); } };
sample_SDK.DependentOptionSetSample.js スクリプト Web リソースを、フォームで使用できる JScript ライブラリに追加します。
フォームの Onload イベントで、イベント ハンドラーが SDK.DependentOptionSet.init 関数を呼び出して、XML Web リソースの名前をパラメーターとして渡すように構成します。[ハンドラのプロパティ] ダイアログ ボックスのフィールドを使用して、"sample_TicketDependentOptionSetConfig.xml" を [関数に渡されるパラメーターのコンマ区切り一覧] フィールドに入力します。
[カテゴリ] フィールドの OnChange イベントで、[関数] を SDK.DependentOptionSet.filterDependentField に設定します。
[関数に渡されるパラメーターのコンマ区切り一覧] テキスト ボックスに、"sample_category", "sample_subcategory" を入力します。
[サブ カテゴリ] フィールドの OnChange イベントで、[関数] を SDK.DependentOptionSet.filterDependentField. に設定します。
[関数に渡されるパラメーターのコンマ区切り一覧] テキスト ボックスに、"sample_subcategory ", "sample_type" を入力します。
すべてのカスタマイズを保存し、公開します。
関連項目
Xrm.Page オブジェクト モデルの使用
Microsoft Dynamics CRM 2015 フォームのコードを記述する
Microsoft Dynamics CRM 2015 での JavaScript の使用
エンティティ フォームのカスタマイズ
Xrm.Page.data.entity 属性 (クライアント側の参照)
Xrm.Page.ui コントロール (クライアント側の参照)
© 2017 Microsoft. All rights reserved. 著作権