D365 Display deeply related information on a form in subgrid

寵の児 提交于 2020-03-04 23:08:33

问题


Have a requirement to show list of Unterweisung (trainings) titles in Contact's form as a subgrid. Please, look at:

Is there a way to display those?

I have tried to append fetchXML to form grid vie JS, but no success there by two reasons:

1) FetchXML is not valid, because of twin-linked entity search, i suppose. If it is not supported, the whole approach is wrong.

2) Even if leaving filtering only for one entity, d365 drops an error Invalid FetchXML on opening Contact form. FetchXML validators are stating opposite.

Estimated full fetchXML (not valid):

<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true">
  <entity name="new_schulungstyp">
    <attribute name="new_name" />
    <attribute name="createdon" />
    <attribute name="new_schulungstypid" />
    <attribute name="new_typ" />
    <attribute name="new_intervall" />
    <order attribute="createdon" descending="false" />
    <filter type="and">
      <condition attribute="statecode" operator="eq" value="0" />
    </filter>
    <link-entity name="new_new_schulungstyp_new_azttigkeit" from="new_schulungstypid" to="new_schulungstypid" visible="false" intersect="true">
      <link-entity name="new_azttigkeit" from="new_azttigkeitid" to="new_azttigkeitid" alias="aa">
        <link-entity name="new_new_profil_new_azttigkeit" from="new_azttigkeitid" to="new_azttigkeitid" visible="false" intersect="true">
          <link-entity name="new_profil" from="new_profilid" to="new_profilid" alias="ab">
            <link-entity name="new_contact_new_profil" from="new_profilid" to="new_profilid" visible="false" intersect="true">
              <link-entity name="contact" from="contactid" to="contactid" alias="ac">
                <filter type="or">
                  <condition attribute="contactid" operator="eq" value="currentContactIdInsertedViaJs" />
                </filter>
              </link-entity>
            </link-entity>
          </link-entity>
        </link-entity>
      </link-entity>
    </link-entity>
    <link-entity name="new_new_betriebsmittel_new_schulungstyp" from="new_schulungstypid" to="new_schulungstypid" visible="false" intersect="true">
      <link-entity name="new_betriebsmittel" from="new_betriebsmittelid" to="new_betriebsmittelid" alias="ad">
        <link-entity name="new_new_betriebsmittel_new_profil" from="new_betriebsmittelid" to="new_betriebsmittelid" visible="false" intersect="true">
          <link-entity name="new_profil" from="new_profilid" to="new_profilid" alias="ae">
            <link-entity name="new_contact_new_profil" from="new_profilid" to="new_profilid" visible="false" intersect="true">
              <link-entity name="contact" from="contactid" to="contactid" alias="af">
                <filter type="or">
                  <condition attribute="contactid" operator="eq" value="currentContactIdInsertedViaJs" />
                </filter>
              </link-entity>
            </link-entity>
          </link-entity>
        </link-entity>
      </link-entity>
    </link-entity>
  </entity>
</fetch> 

JS code with single entity filter:

function filterTrainings(executionContext) {
    var formContext = executionContext.getFormContext();
    var guid = Xrm.Page.data.entity.getId();
    var fullname = formContext.getAttribute("fullname").getValue();

    //var fullName = formContext.getAttribute("fullname_d").getValue();
var fetchXML = "<fetch>";
    fetchXML+=  "<entity name='new_schulungstyp'>";
    fetchXML+= "<attribute name='new_name' />";
    fetchXML+= "<attribute name='createdon' />";
    fetchXML+= "<attribute name='new_schulungstypid' />";
    fetchXML+= "<attribute name='new_typ' />";
    fetchXML+= "<attribute name='new_intervall' />";
    fetchXML+= "<order attribute='createdon' descending='false' />";
    fetchXML+= "<filter type='and'>";
    fetchXML+= "<condition attribute='statecode' operator='eq' value='0' />";
    fetchXML+=  "</filter>";
    fetchXML+= "<link-entity name='new_new_schulungstyp_new_azttigkeit' from='new_schulungstypid' to='new_schulungstypid' visible='false' intersect='true'>";
    fetchXML+= "<link-entity name='new_azttigkeit' from='new_azttigkeitid' to='new_azttigkeitid' alias='aj'>";
    fetchXML+= "<link-entity name='new_new_profil_new_azttigkeit' from='new_azttigkeitid' to='new_azttigkeitid' visible='false' intersect='true'>";
    fetchXML+= "<link-entity name='new_profil' from='new_profilid' to='new_profilid' alias='ak'>";
    fetchXML+= "<link-entity name='new_contact_new_profil' from='new_profilid' to='new_profilid' visible='false' intersect='true'>";
    fetchXML+= "<link-entity name='contact' from='contactid' to='contactid' alias='al'>";
    fetchXML+= "<filter type='and'>";
    fetchXML+= "<condition attribute='contactid' operator='eq' value='"+guid+"' />";
    fetchXML+= "</filter>";
    fetchXML+=  "</link-entity>";
    fetchXML+=  "</link-entity>";
    fetchXML+= "</link-entity>";
    fetchXML+=  "</link-entity>";
    fetchXML+= "</link-entity>";
    fetchXML+=  "</link-entity>";
    fetchXML+=  "</entity>";
    fetchXML+=  "</fetch>";

    var grid = formContext.getControl("relatedTrainings");

    if (grid == null) {
        setTimeout(function () {
            filterTrainings(executionContext);
        }, 2000);
        return;
    } else {
        grid.getGrid().setParameter("fetchXml", filterTrainings); //set the fetch xml to the sub grid
        console.log("refresh............")
    }
}

回答1:


Managed to figure that one out. I am getting all required ID's that should be displayed in subgrid by subsequently sending get requests. Most important here is to manage async nature of promises. Then I build a filter that forces subgrid to show only entities, that are in related ID collection

Posting my solution:

function filterTrainings(executionContext) {
var formContext = executionContext.getFormContext();
var trainigsControl = formContext.getControl("relatedTrainings").getGrid();
var guid = Xrm.Page.data.entity.getId();
console.log(guid);

var relatedProfiles = [];
var relatedTatigkeiten = [];
var relatedBetriebsmittelGruppen = [];
var unterweisungTypen = [];
var xml;

GetRelatedProfiles()
    .then(() => GetRelatedTatigkeiten().then(GetTatigkeitenRelatedUnterweisungTypen).then(() => GetRelatedBetriebsmittel().then(GetBetriebsmittelRelatedUnterweisungTypen).then(buildFetchXMLAndUpdateGrid)));

function buildFetchXMLAndUpdateGrid() {
    getUniques(unterweisungTypen);
    var values = unterweisungTypen.map(val => `<value>${val}</value>`);
    console.log(values);

    xml = `<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
    <entity name="new_schulungstyp">
        <attribute name="new_name" />
        <attribute name="createdon" />
        <attribute name="new_schulungstypid" />
        <attribute name="new_typ" />
        <attribute name="new_intervall" />
        <order attribute="createdon" descending="false" />
        <filter type="and">
            <condition attribute="new_schulungstypid" operator="in">${values.join('')}</condition>
        </filter>
    </entity>
</fetch>`;
    console.log(xml);
    trainigsControl.setParameter("fetchXML", xml);
    trainigsControl.refresh();
    return xml;
}


function GetRelatedProfiles() {
    return Xrm.WebApi.online.retrieveMultipleRecords("new_contact_new_profil", "?$select=new_profilid&$filter=contactid eq " + guid).then(
        function success(result) {
            for (var i = 0; i < result.entities.length; i++) {
                relatedProfiles.push(result.entities[i]["new_profilid"]);
            }
        },
        function (error) {
            console.log(error.message);
            // handle error conditions
        }
    );
}

function getUniques(arr) {
    var uniques = [];
    arr.forEach(item => {
        if (uniques.indexOf(item) === -1) {
            uniques.push(item);
        }
    });
    arr = uniques;
}

function GetRelatedTatigkeiten() {
    return Promise.all(relatedProfiles.map(profile =>
        Xrm.WebApi.online.retrieveMultipleRecords("new_new_profil_new_azttigkeit", `?$select=new_azttigkeitid&$filter=new_profilid eq ${profile}`).then(
            function success(result) {
                for (var i = 0; i < result.entities.length; i++) {
                    relatedTatigkeiten.push(result.entities[i]["new_azttigkeitid"]);
                }
            }, function (error) {
                console.log(error.message);
                // handle error conditions
            }
        )
    )).then(() => getUniques(relatedTatigkeiten));
}

function GetRelatedBetriebsmittel() {
    return Promise.all(relatedProfiles.map(profile =>
        Xrm.WebApi.online.retrieveMultipleRecords("new_new_betriebsmittel_new_profil", "?$select=new_betriebsmittelid&$filter=new_profilid eq " + profile).then(
            function success(result) {
                for (var i = 0; i < result.entities.length; i++) {
                        relatedBetriebsmittelGruppen.push(result.entities[i]["new_betriebsmittelid"])
                }
            }, function (error) {
                console.log(error.message);
                // handle error conditions
            }
        )
    )).then(() => getUniques(relatedTatigkeiten));
}

function GetBetriebsmittelRelatedUnterweisungTypen() {
    return Promise.all(relatedBetriebsmittelGruppen.map(betriebsmittel =>
        Xrm.WebApi.online.retrieveMultipleRecords("new_new_betriebsmittel_new_schulungstyp", "?$select=new_schulungstypid&$filter=new_betriebsmittelid eq " + betriebsmittel).then(
            function success(result) {
                for (var i = 0; i < result.entities.length; i++) {
                    unterweisungTypen.push(result.entities[i]["new_schulungstypid"]);
                }
            }, function (error) {
                console.log(error.message);
                // handle error conditions
            }
        )
    )).then(() => getUniques(unterweisungTypen));
}

function GetTatigkeitenRelatedUnterweisungTypen() {
    return Promise.all(relatedTatigkeiten.map(tatigkeiten =>
        Xrm.WebApi.online.retrieveMultipleRecords("new_new_schulungstyp_new_azttigkeit", "?$select=new_schulungstypid&$filter=new_azttigkeitid eq " + tatigkeiten).then(
            function success(result) {
                for (var i = 0; i < result.entities.length; i++) {
                        unterweisungTypen.push(result.entities[i]["new_schulungstypid"]);
                }
            }, function (error) {
                console.log(error.message);
                // handle error conditions
            }
        ))).then(() => getUniques(unterweisungTypen));
    }

}



来源:https://stackoverflow.com/questions/60277126/d365-display-deeply-related-information-on-a-form-in-subgrid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!