Кастомизация
19
Мар
0

Мини-редактор вложенного Представления

Сегодня сделаем очень интересную штуку: редактор вложенного представления. Причем в качестве вспомогательных материалов будем использовать только обычные поля CRM и JS-код.

Начнем (потирая ручки… 🙂 ):

  • Вынесите на форму Организации вложенное Представление по связи «Головная организация» с именем «accounts». Создайте для Организации новое Представление с полями: Название, Основной контакт, Основной телефон и Электронная почта. Выберите это представление в качестве единственного для вложенного Представления;
  • Создайте для объекта Организация следующие поля:
    • Название (new_name) – текстовое поле;
    • Основной контакт (new_contact) – лукап на Контакт;
    • Основной телефон (new_phone) – текстовое поле;
    • Электронная почта (new_email) – текстовое поле (тип e-mail);
    • GUID (new_guid) – текстовое поле.

    Вынесите их на форму над вложенным Представлением. GUID сделайте неактивным (а когда наиграетесь можете и скрыть);

  • Создайте в CRM следующие PNG Веб-ресурсы (с такими же именами):
  • Добавьте в CRM следующие JS библиотеки:

    … и добавьте их к форме Организации;

  • Создайте JS Веб-ресурс с именем editor.js и таким кодом:
    function get() {
        var grid = document.getElementById('accounts').control;
        for (var r = 0; r < grid.getRecordsFromInnerGrid().length; r++) {
            if (grid.get_selectedIds()[0] == grid.getRecordsFromInnerGrid()[r][0]) {
                var acc_id = grid.getRecordsFromInnerGrid()[r][3].cells[2].firstChild.firstChild.getAttribute('id').substring(28, 64);
                Xrm.Page.getAttribute("new_guid").setValue(acc_id);
                Xrm.Page.getAttribute("new_name").setValue(grid.getRecordsFromInnerGrid()[r][3].cells[2].innerText);
    
                var cont_id = grid.getRecordsFromInnerGrid()[r][3].cells[3].firstChild.firstChild.firstChild.firstChild.getAttribute('oid').substring(1, 37);
                var cont_name = grid.getRecordsFromInnerGrid()[r][3].cells[3].innerText;
                var lookup = [{ id: cont_id, name: cont_name, typename: "contact"}];
                Xrm.Page.getAttribute("new_contact").setValue(lookup);
    
                Xrm.Page.getAttribute("new_phone").setValue(grid.getRecordsFromInnerGrid()[r][3].cells[4].innerText);
                Xrm.Page.getAttribute("new_email").setValue(grid.getRecordsFromInnerGrid()[r][3].cells[5].innerText);
            }
        }
    }
    
    function add() {
        var name = Xrm.Page.getAttribute("new_name").getValue();
        var contact = Xrm.Page.getAttribute("new_contact").getValue();
        var phone = Xrm.Page.getAttribute("new_phone").getValue();
        var email = Xrm.Page.getAttribute("new_email").getValue();
        var parentName = Xrm.Page.getAttribute("name").getValue();
        var parentId = Xrm.Page.data.entity.getId();
    
        if (!name || !contact || !phone || !email || !parentName || !parentId) return;
    
        // Создаем объект представляющий собой Организацию
        var account = new Object();
        account.Name = name;
        account.Telephone1 = phone;
        account.EMailAddress1 = email;
        account.PrimaryContactId = { Id: contact[0].id, LogicalName: "contact", Name: contact[0].name };
        account.ParentAccountId = { Id: parentId, LogicalName: "account", Name: parentName };
    
        createRecord(account, "AccountSet", complete, null);
    }
    
    function createRecord(entityObject, odataSetName, successCallback, errorCallback) {
        //alert(window.JSON.stringify(entityObject));
        // Конечная точка OData
        var ODATA_ENDPOINT = Xrm.Page.context.getServerUrl() + "/XRMServices/2011/OrganizationData.svc/" + odataSetName;
        // Вызываем асинхронную функцию AJAX для создания записи CRM через OData
        $.ajax({
            type: "POST",
            contentType: "application/json; charset=utf-8",
            datatype: "json",
            url: ODATA_ENDPOINT,
            data:  window.JSON.stringify(entityObject),
            beforeSend: function (XMLHttpRequest) {
                // Specifying this header ensures that the results will be returned as JSON.
                XMLHttpRequest.setRequestHeader("Accept", "application/json");
            },
            success: function (data, textStatus, XmlHttpRequest) {
                successCallback(data.d, textStatus, XmlHttpRequest);
            },
            error: function (XmlHttpRequest, textStatus, errorThrown) {
                errorHandler(XmlHttpRequest, textStatus, errorThrown);
            }
        });
    }
    
    function upd() {
        var name = Xrm.Page.getAttribute("new_name").getValue();
        var contact = Xrm.Page.getAttribute("new_contact").getValue();
        var phone = Xrm.Page.getAttribute("new_phone").getValue();
        var email = Xrm.Page.getAttribute("new_email").getValue();
        var guid = Xrm.Page.getAttribute("new_guid").getValue();
    
    
        if (!name || !contact || !phone || !email || !guid) return;
    
        // Формируем "пакет" обновлений
        var changes = {
            Name: name,
            Telephone1: phone,
            EMailAddress1: email,
            PrimaryContactId: {
                Id: contact[0].id,
                LogicalName: "contact",
                Name: contact[0].name
            }
        };
    
        updateRecord(guid, changes, "AccountSet", complete, errorHandler);
    }
    
    function updateRecord(id, entityObject, odataSetName, successCallback, errorCallback) {
        // Конечная точка OData
        var ODATA_ENDPOINT = Xrm.Page.context.getServerUrl() + "/XRMServices/2011/OrganizationData.svc/" + odataSetName;
        // Вызываем асинхронную функцию AJAX для обновления записи CRM через OData
        $.ajax({
            type: "POST",
            contentType: "application/json; charset=utf-8",
            datatype: "json",
            data: window.JSON.stringify(entityObject), // Парсим "пакет" обновлений
            url: ODATA_ENDPOINT + "(guid'" + id + "')",
            beforeSend: function (XMLHttpRequest) {
                XMLHttpRequest.setRequestHeader("Accept", "application/json"); // Определяем заголовок, чтобы результат был возвращен в формате JSON.
                XMLHttpRequest.setRequestHeader("X-HTTP-Method", "MERGE"); // Определяем HTTP метод MERGE чтобы обновить только то что мы отправим.
            },
            success: function (data, textStatus, XmlHttpRequest) {
                // MERGE не возвращает никаких данных, поэтому мы добавляем id к объекту данных и передаем его в функцию обратного вызова
                data = new Object();
                data.id = id;
                successCallback(data, textStatus, XmlHttpRequest);
            },
            error: function (XmlHttpRequest, textStatus, errorThrown) {
                errorHandler(XmlHttpRequest, textStatus, errorThrown);
            }
        });
    }
    
    // Функция вызываемая при неудачном обновлении
    function errorHandler(xmlHttpRequest, textStatus, errorThrow) {
        alert("Error : " + textStatus + ": " + xmlHttpRequest.statusText);
    }
    
    function complete(data, textStatus, XmlHttpRequest) {
        var grid = document.getElementById("accounts"); // ID вложенного Представления
        grid.control.refresh(); // обновляем...
    }
    // Очищаем поля
    function clear() {
        Xrm.Page.getAttribute("new_name").setValue(null);
        Xrm.Page.getAttribute("new_contact").setValue(null);
        Xrm.Page.getAttribute("new_phone").setValue(null);
        Xrm.Page.getAttribute("new_email").setValue(null);
        Xrm.Page.getAttribute("new_guid").setValue(null);
    }
    

    Этот код состоит из нескольких функций:

    • get – берет первую выделенную строку из вложенного Представления и помещает значения ее столбцов в кастомные поля на форме Организации;
    • add – добавляет к текущей записи Организации дочернюю Организацию, беря для нее данные из кастомных полей;
    • createRecord – функция формирует и отправляет oData-запрос создания записи на основе данных, переданных из функции add;
    • upd – обновляет дочернюю записи Организации, id которой находится в поле GUID, данными других кастомных полей;
    • updateRecord –формирует и отправляет oData-запрос обновления записи на основе данных, переданных из функции upd;
    • errorHandler – обрабатывает ошибки oData-запросов;
    • complete – в случае успешного выполнения oData-запросов обновялет вложенное Представление;
    • clear – очищает кастомные поля.

    Подключите этот Веб-ресурс к форме Организации.

  • Экспортируйте Ленту Организации и замените узел RibbonDiffXml таким кодом:
    <RibbonDiffXml>
      <CustomActions>
        <CustomAction Id="add.CustomAction"
                      Location="Mscrm.Form.account.MainTab.Collaborate.Controls._children"
                      Sequence="1" >
          <CommandUIDefinition>
            <Button Id="add.Button"
                    LabelText="Создать"
                    ToolTipTitle="Создать"
                    ToolTipDescription="Создать"
                    TemplateAlias="o1"
                    Sequence="1"
                    Image32by32="$webresource:new_add_32.png"
                    Command="add.CommandDefinition" />
          </CommandUIDefinition>
        </CustomAction>
        <CustomAction Id="get.CustomAction"
                    Location="Mscrm.SubGrid.account.MainTab.Collaborate.Controls._children"
                    Sequence="2" >
          <CommandUIDefinition>
            <Button Id="get.Button"
                    LabelText="Получить"
                    ToolTipTitle="Получить"
                    ToolTipDescription="Получить"
                    TemplateAlias="o1"
                    Sequence="2"
                    Image32by32="$webresource:new_get_32.png"
                    Command="get.CommandDefinition" />
          </CommandUIDefinition>
        </CustomAction>
        <CustomAction Id="upd.CustomAction"
                    Location="Mscrm.Form.account.MainTab.Collaborate.Controls._children"
                    Sequence="3" >
          <CommandUIDefinition>
            <Button Id="upd.Button"
                    LabelText="Обновить"
                    ToolTipTitle="Обновить"
                    ToolTipDescription="Обновить"
                    TemplateAlias="o1"
                    Sequence="3"
                    Image32by32="$webresource:new_upd_32.png"
                    Command="upd.CommandDefinition" />
          </CommandUIDefinition>
        </CustomAction>
        <CustomAction Id="clear.CustomAction"
                    Location="Mscrm.Form.account.MainTab.Collaborate.Controls._children"
                    Sequence="4" >
          <CommandUIDefinition>
            <Button Id="clear.Button"
                    LabelText="Очистить"
                    ToolTipTitle="Очистить"
                    ToolTipDescription="Очистить"
                    TemplateAlias="o1"
                    Sequence="4"
                    Image32by32="$webresource:new_clear_32.png"
                    Command="clear.CommandDefinition" />
          </CommandUIDefinition>
        </CustomAction>
      </CustomActions>
      <Templates>
        <RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates>
      </Templates>
      <CommandDefinitions>
        <CommandDefinition Id="add.CommandDefinition">
          <EnableRules>
            <EnableRule Id="Mscrm.Enabled" />
          </EnableRules>
          <DisplayRules/>
          <Actions>
            <JavaScriptFunction Library="$webresource:new_editor.js" FunctionName="add" />
          </Actions>
        </CommandDefinition>
        <CommandDefinition Id="get.CommandDefinition">
          <EnableRules>
            <EnableRule Id="Mscrm.Enabled" />
          </EnableRules>
          <DisplayRules/>
          <Actions>
            <JavaScriptFunction Library="$webresource:new_editor.js" FunctionName="get" />
          </Actions>
        </CommandDefinition>
        <CommandDefinition Id="upd.CommandDefinition">
          <EnableRules>
            <EnableRule Id="Mscrm.Enabled" />
          </EnableRules>
          <DisplayRules/>
          <Actions>
            <JavaScriptFunction Library="$webresource:new_editor.js" FunctionName="upd" />
          </Actions>
        </CommandDefinition>
        <CommandDefinition Id="clear.CommandDefinition">
          <EnableRules>
            <EnableRule Id="Mscrm.Enabled" />
          </EnableRules>
          <DisplayRules/>
          <Actions>
            <JavaScriptFunction Library="$webresource:new_editor.js" FunctionName="clear" />
          </Actions>
        </CommandDefinition>
      </CommandDefinitions>
      <RuleDefinitions>
        <TabDisplayRules/>
        <DisplayRules/>
        <EnableRules/>
      </RuleDefinitions>
      <LocLabels />
    </RibbonDiffXml>
    

    Здесь у нас четыре кнопки, одно на вложенной Ленте (которая появляется, когда Вы выделяете записи во вложенном Представлении) и три на основное Ленте формы.
    Импортируйте Ленту обратно в CRM.

Ну, вот и все… идем жать кнопки… 🙂




Комментарии (0)

*

code