Кастомизация
22
Июн
5

Три новых лукапа

Как Вы значете в CRM существует 4 «вида» лукапов:

  • Обычный – его мы можем создать через интерфейс (связб N:1);
  • Клиент – системный лукап, присутствует на некоторых формах (например Возможной сделке);
  • Лукап для нескольких объектов – представляет собой простой лукап (связь N:1), но может ссылаться на один из нескольких (предопределенных) объектов;
  • Мульти-лукап – в этом виде лукапа Вы можете выбрать сразу несколько записай (причем из разных объектов), присутствует, например, на форме Электронной почты.

Обычный нам не интересен (любой может его сделать). «Клиента» мы уже проходили 🙂 Рассмотрим как создать оставшиеся два + еще кое-что 🙂

Лукап без связи

Начнем с «кое-что» 🙂 А именно: создадим «виртуальный» лукап, не имеющий физической связи. Т.е. для его создания нам понадобятся только два текстовых поля и JavaScript!

  • Для начала создайте два nvarchar-поля (в 1000 симолов – прозапас 🙂 ) для нужного Вам объекта и поместите их на форму (П.С. эти же поля мы будем использовать в двух последующих примерах). Первое поле будет подменяться кодом на «виртуальный» лукап, а во втором мы будем хранить значения выбранные в лукапе (т.к. при сохранении карточки лукап будет «уничтожен»);


  • Далее поместите на онлоад формы такой код:
    // Функция формирует виртуальный лукап
    crmForm.createVirtualLookupS = function(idField, valueField, typecode, typename, isCustomEntity) {
        // Формируем строку с иконками
    	var iconURL;
        if (isCustomEntity)
            iconURL = "/_imgs/icon.aspx?objectTypeCode=" + typecode + "&iconType=GridIcon&inProduction=1&cache=1";
        else
            iconURL = "/_imgs/ico_16_" + typecode + ".gif"; 
        // Запоминаем начальные параметры исходного поля
    	var tmpid = idField.id;
        var tmpid_req = idField.req;
        var tmpid_tabIndex = idField.tabIndex;
        var tmpid_onchange = idField.onchange;
        var tmpid_disabled = idField.Disabled; 
            
        // Формируем HTML-код лукапа
    	outerHTML = "";
        outerHTML += "<td id='" + tmpid + "_d'>";
        outerHTML +=    "<table class='ms-crm-Lookup' cellpadding='0' cellspacing='0' width='100%' style='table-layout:fixed;'>";
        outerHTML +=        "<tr>";
        outerHTML +=            "<td>";
        outerHTML +=                "<div ime-mode='auto' class='ms-crm-Lookup' tabindex='" + tmpid_tabIndex + "'></div>";
        outerHTML +=                "<label class='ms-crm-Hidden-NoBehavior' for='" + tmpid + "_ledit'></label>";
        outerHTML +=                "<input class='ms-crm-Hidden-NoBehavior' ime-mode='auto' type='text' tabindex='" + tmpid_tabIndex + "' id='" + tmpid + "_ledit' maxlength='100'/>";
        outerHTML +=            "</td>";
        outerHTML +=            "<td width='25' CLASS='Lookup_RenderButton_td'>";
        outerHTML +=                "<img src='/_imgs/btn_off_lookup.gif' id='" + tmpid + "' class='ms-crm-Lookup' tabIndex='" + tmpid_tabIndex + "' Style='ime-mode:auto' resolveemailaddress='0' showproperty='1' autoresolve='1' defaulttype='0' lookuptypes='" + typecode + "' lookuptypenames='" + typename + ":" + typecode + "' lookuptypeIcons='" + iconURL + "' lookupbrowse='0' lookupstyle='single' req='" + tmpid_req + "' >";
        outerHTML +=                "<a href='#' onclick='previousSibling.click();' tabindex='-1'></a>";
        outerHTML +=            "</td>";
        outerHTML +=        "</tr>";
        outerHTML +=    "</table>";
        outerHTML += "</td>";
            
        // Подменяем текстовое поле лукапом
    	idField.outerHTML = outerHTML;
     
        // Возвращаем лукапу начальные параметры исходного поля
    	idField = document.getElementById(tmpid);
        idField.aoUnattachedEvents = new Array();
        idField.Disabled = tmpid_disabled;
    	// Формируем событие onChange для лукапа
    	idField.attachEvent('onchange', 
            // При изменениии лукапа, записываем параметры выбранной записи (отображаемое значение и id) в "поле-хранилище" (с разделителем "|")
    		function() {
                if (idField.DataValue != null) {
    				var lkp = idField.DataValue;
    				valueField.DataValue = lkp[0].name + "|" + lkp[0].id;
    			} else {
    				// Очищаем "поле-хранилище" если в лукапе ничего не содержится
    				valueField.DataValue = "";
    			}
            }
        );
        
    	// Если при загрузке "поле-хранилище" не пустое записываем его содержимое в лукап
        if (valueField.DataValue != null && valueField.DataValue != "") {
            var luItems = new Array();
            // Разбиваем строку на символы "|" и...
    		var item = valueField.DataValue.split('|'); 
    		// ... помещаем элементы в массив
            luItems[0] = new LookupControlItem(item[1], typecode, item[0]);
            idField.DataValue = luItems;
        }
    } 
    
    // Вызываем функцию формирующую виртуальный лукап
    // Параметры: текстовое поле (которое будет заменено лукапом), текстовое "поле-хранилище", код объекта, имя объека, булево значение определеяющее содержит ля лукап кастомный объект
    crmForm.createVirtualLookupS(crmForm.all.new_test1, crmForm.all.new_test2, '1', 'account', false);
    

    Разбор полетов:

    • Код состоит из двух частей: кастомной функции формирующей виртуальныей лукап и ее вызова с передачей необхдимых параметров;
    • Перед формирование лукапа происходит считывание параметров поля, которое будет заменено на лукап (например состояние деактивации);
    • Затем формируется HTML-код одиночного лукапа;
    • Записываем в лукап параметры считанные с исходного поля:
    • Формируем событие onChange для лукапа — в данном случае нам нужно только записать выбранную в лукапе запись в поле-хранитель (но Вы можете дописать и другую логику);
    • Далее при формировании лукапа нам нужно считать из поля-хранителя значения (если они там вообще есть) и поместить их в лукап)
    • Ну, и на последок происходит вызов самой функции формирующей лукап с передачей необходимых параметров (поэтому не забудьте их подправить на свои!
      З.Ы. логика работы двух других, ниже приведенных, листенгов аналогична этой – поэтому я не буду их расписвать 🙂
  • Идем пробовать лукап… 🙂



Лукап для нескольких объектов

Как было сказано этот вид лукапа позволяет выбрать одну запись из из нескольких предопределенных объектов. Реализуем:

  • Если Вы выполнили предыдущий пример, то все что Вам нужно это поместить на онлоад формы такой код (если же нет, то создайте два текстовых поля и поместите и на форму):
    // Функция формирует виртуальный лукап
    crmForm.createVirtualLookupM1 = function(idField, valueField, lookuptypeIcons, lookuptypenames, lookuptypes) {
        // Запоминаем начальные параметры исходного поля
    	var tmpid = idField.id;
        var tmpid_req = idField.req;
        var tmpid_tabIndex = idField.tabIndex;
        var tmpid_onchange = idField.onchange;
        var tmpid_disabled = idField.Disabled; 
    	
    	// Формируем HTML-код лукапа
        outerHTML = "";
        outerHTML += "<td id='" + tmpid + "_d'>";
        outerHTML +=    "<table class='ms-crm-Lookup' cellpadding='0' cellspacing='0' width='100%' style='table-layout:fixed;'>";
        outerHTML +=        "<tr>";
        outerHTML +=            "<td>";
        outerHTML +=                "<div ime-mode='auto' class='ms-crm-Lookup' tabindex='" + tmpid_tabIndex + "'></div>";
        outerHTML +=                "<label class='ms-crm-Hidden-NoBehavior' for='" + tmpid + "_ledit'></label>";
        outerHTML +=                "<input class='ms-crm-Hidden-NoBehavior' ime-mode='auto' type='text' tabindex='" + tmpid_tabIndex + "' id='" + tmpid + "_ledit' maxlength='100'/>";
        outerHTML +=            "</td>";
        outerHTML +=            "<td width='25' CLASS='Lookup_RenderButton_td'>";
        outerHTML +=                "<img src='/_imgs/btn_off_lookup.gif' id='" + tmpid + "' class='ms-crm-Lookup' tabIndex='" + tmpid_tabIndex + "' Style='ime-mode:auto' resolveemailaddress='0' showproperty='1' autoresolve='1' defaulttype='0' lookuptypes='" + lookuptypes + "' lookuptypenames='" + lookuptypenames + "' lookuptypeIcons='" + lookuptypeIcons + "' lookupbrowse='0' lookupstyle='single' req='" + tmpid_req + "' >";
        outerHTML +=                "<a href='#' onclick='previousSibling.click();' tabindex='-1'></a>";
        outerHTML +=            "</td>";
        outerHTML +=        "</tr>";
        outerHTML +=    "</table>";
        outerHTML += "</td>";
    	
    	// Подменяем текстовое поле лукапом
        idField.outerHTML = outerHTML;
    
    	// Возвращаем лукапу начальные параметры исходного поля
        idField = document.getElementById(tmpid);
        idField.aoUnattachedEvents = new Array();
        idField.Disabled = tmpid_disabled;
    	// Формируем событие onChange для лукапа
    	idField.attachEvent('onchange', 
            // При изменениии лукапа, записываем параметры выбранной записи в "поле-хранилище" (с разделителем "|")
    		function() {
                if (idField.DataValue != null) {
    				var lkp = idField.DataValue;
    				valueField.DataValue = lkp[0].name + "|" + lkp[0].id + "|" + lkp[0].typename;
    			} else {
    				// Очищаем "поле-хранилище" если в лукапе ничего не содержится
    				valueField.DataValue = "";
    			}
            }
        );
        // Если при загрузке "поле-хранилище" не пустое записываем его содержимое в лукап
        if (valueField.DataValue != null && valueField.DataValue != "") {
            // Разбиваем строку на символы "|" и помещаем элементы в массив
    		var item = valueField.DataValue.split('|'); 
            
    		// Формируем массив со значениями для лукапа
            var lookupData = new Array();
            var lookupItem= new Object();
            lookupItem.id = item[1];
            lookupItem.typename = item[2];
            lookupItem.name = item[0];
    		lookupData[0] = lookupItem;
    		
    		// Помещаем массив в лукап
            idField.DataValue = lookupData;
        }
    } 
    
    // Параметры луапа
    // Иконки
    lookuptypeIcons = '/_imgs/ico_16_1.gif:/_imgs/ico_16_2.gif:/_imgs/ico_16_4.gif:/_imgs/ico_16_8.gif';
    // Имена объектов и их коды
    lookuptypenames = 'account:1,contact:2,lead:4,systemuser:8';
    // Коды объектов
    lookuptypes = '1,2,4,8';
    
    // Вызываем функцию формирующую виртуальный лукап
    // Параметры: текстовое поле (которое будет заменено лукапом), текстовое "поле-хранилище", иконки, имена объеков с кодами, коды объектов
    crmForm.createVirtualLookupM1(crmForm.all.new_test1, crmForm.all.new_test2, lookuptypeIcons, lookuptypenames, lookuptypes);
    

    Логика его работы описана в предыдущем примере!

  • Смотрим на лукап 🙂



Мульти-лукап

Самый интересный «подвид» лукапа 🙂 Позволяет выбрать сразу несколько записей из нескольких объектов!

  • Создайте два текстовыйх поля для объекта (если Вы их еще не создали) и поместите на форму нужного объекта!
  • На онлоад формы вешаем следующий код:
    // Функция формирует виртуальный лукап
    crmForm.createVirtualLookupM2 = function(idField, valueField, lookuptypeIcons, lookuptypenames, lookuptypes) {
        // Запоминаем начальные параметры исходного поля
    	var tmpid = idField.id;
        var tmpid_req = idField.req;
        var tmpid_tabIndex = idField.tabIndex;
        var tmpid_onchange = idField.onchange;
        var tmpid_disabled = idField.Disabled; 
    	
    	// Формируем HTML-код лукапа
        outerHTML = "";
        outerHTML += "<td id='" + tmpid + "_d'>";
        outerHTML +=    "<table class='ms-crm-Lookup' cellpadding='0' cellspacing='0' width='100%' style='table-layout:fixed;'>";
        outerHTML +=        "<tr>";
        outerHTML +=            "<td>";
        outerHTML +=                "<div ime-mode='auto' class='ms-crm-Lookup' tabindex='" + tmpid_tabIndex + "'></div>";
        outerHTML +=                "<label class='ms-crm-Hidden-NoBehavior' for='" + tmpid + "_ledit'></label>";
        outerHTML +=                "<input class='ms-crm-Hidden-NoBehavior' ime-mode='auto' type='text' tabindex='" + tmpid_tabIndex + "' id='" + tmpid + "_ledit' maxlength='100'/>";
        outerHTML +=            "</td>";
        outerHTML +=            "<td width='25' CLASS='Lookup_RenderButton_td'>";
        outerHTML +=                "<img src='/_imgs/btn_off_lookup.gif' id='" + tmpid + "' class='ms-crm-Lookup' tabIndex='" + tmpid_tabIndex + "' Style='ime-mode:auto' resolveemailaddress='0' showproperty='1' autoresolve='1' defaulttype='0' lookuptypes='" + lookuptypes + "' lookuptypenames='" + lookuptypenames + "' lookuptypeIcons='" + lookuptypeIcons + "' lookupbrowse='0' lookupstyle='multi' req='" + tmpid_req + "' >";
        outerHTML +=                "<a href='#' onclick='previousSibling.click();' tabindex='-1'></a>";
        outerHTML +=            "</td>";
        outerHTML +=        "</tr>";
        outerHTML +=    "</table>";
        outerHTML += "</td>";
            
        // Подменяем текстовое поле лукапом
    	idField.outerHTML = outerHTML;
    
    	// Возвращаем лукапу начальные параметры исходного поля
        idField = document.getElementById(tmpid);
        idField.aoUnattachedEvents = new Array();
        idField.Disabled = tmpid_disabled;
    	// Формируем событие onChange для лукапа
    	idField.attachEvent('onchange', 
            // При изменениии лукапа, записываем выбранные записи (с разделителем "=") и их параметры (с разделителем "|") в "поле-хранилище"
    		function() {
                if (idField.DataValue != null) {
    				var lkp = idField.DataValue;
    				var result = "";
    				
    				for (var record in lkp) {
    					var val = lkp[record];
    					result += val['name'] + "|" + val['id'] + "|" + val['typename'] + "=";
    				}
    				valueField.DataValue = result;
    			} else {
    				// Очищаем "поле-хранилище" если в лукапе ничего не содержится
    				valueField.DataValue = "";
    			}
            }
        );
        
    	// Если при загрузке "поле-хранилище" не пустое записываем его содержимое в лукап
    	if (valueField.DataValue != null && valueField.DataValue != "") {
    		// Разбиваем строку на отдельные записи
    		var records = valueField.DataValue.split('=');
    		
    		var x = 0;
    		var lookupData = new Array();
    		
    		// Просматриваем все записи
    		for (var record in records) {
    			var val = records[record];
    
    			if (val.length > 0) {
    				// Разбиваем запись на отдельные параметры
    				var item = val.split('|')
    				
    				// Формируем массив лукапа
    				var lookupItem= new Object();
    				lookupItem.id = item[1];
    				lookupItem.typename = item[2];
    				lookupItem.name = item[0];
     
    				lookupData[x++] = lookupItem;
    			}
    		}
    		// Помещаем массив в лукап
    		idField.DataValue = lookupData;
        }
    } 
    
    // Параметры луапа
    // Иконки
    lookuptypeIcons = '/_imgs/ico_16_1.gif:/_imgs/ico_16_2.gif:/_imgs/ico_16_4.gif:/_imgs/ico_16_8.gif';
    // Имена объектов и их коды
    lookuptypenames = 'account:1,contact:2,lead:4,systemuser:8';
    // Коды объектов
    lookuptypes = '1,2,4,8';
    
    // Вызываем функцию формирующую виртуальный лукап
    // Параметры: текстовое поле (которое будет заменено лукапом), текстовое "поле-хранилище", иконки, имена объеков с кодами, коды объектов
    crmForm.createVirtualLookupM2(crmForm.all.new_test1, crmForm.all.new_test2, lookuptypeIcons, lookuptypenames, lookuptypes);
    

    За описанием работы обращаемся к первому примеру;

  • Публикуем и смотрим!



P.S. В данных примерах не реализовано, но в продуктивной среде лучше бы скрыть поле-хранитель 🙂

Комментарии (5)
  • mc707 22.06.2010

    Спасибо за решение!

    Есть одна проблемка — пытаюсь создать мультилукап для кастомной сущности.
    Посмотрел по адресу http://crm/sdk/list.aspx код этой сущности — 10013, поменял в коде.
    При начале выбора лукапа у меня выходит ошибка «У вас нет достаточных прав для открытия этого диалогового окна «Поиск»». Хотя захожу под ролью системного администратора.

  • slivka_83 22.06.2010

    Добрый день.

    Решение довольно старое, т.к. оно не поддреживаемое, вполне вероятно что решение перестало работать после очередного ролапа…

  • Michael 22.06.2010

    Vsyo otli4no rabotaet — rollup 14

    Spasibo ogromnii =)

  • Michael 22.06.2010

    Rabotaet! Rollup 14.

    Spasibo!

  • Борис Богданов 22.06.2010

    В CRM 2013, кто-нибудь писал кастомный мульти-лукап с кастомными сущностями? Поделитесь опытом плиз.

*

code