Добавление вкладки в CRM коробки Битрикс24

Углубленное изучение Битрикс
  • Добавление вкладки в CRM коробки Битрикс24

    Антон Долганин 21 Июля 2016 12:29 4275
    В этом посте я покажу, как легко и просто добавить вкладку в сущность CRM. И не просто добавить, а вывести там свой контент.

    Screenshot_2.png

    Для простоты изложения будем вести разговор о сделке, хотя все сказанное применимо практически к любой карточке CRM.

    Я пойду по шагам, чтобы вы могли остановиться на том или ином шаге, или доработать его под себя. Код целиком вы получите в конце поста.

    0. Добавляем вкладку через интерфейс, вручную. Называйте ее как хотите, но учтите, что в коде ниже вы будете опираться на название.

    Screenshot_3.png

    1. Обрабатываем открытие вкладки. Тут все просто и понятно и одинаково для всех. Срабатывает всегда на открытии _любой_ вкладки. А на массив arTabLoading пока не обращайте внимания.
    var arTabLoading = []; 
    BX.ready(function(){
       //обработка открытия вкладки
       BX.addCustomEvent('BX_CRM_INTERFACE_FORM_TAB_SELECTED', BX.delegate(function(self, name, tab_id){
    
       }));
    }); 

    2. В моем случае я добавлял вкладку под названием Остатки. Тут ищется вхождение в название слова "остатки" (чтобы понять, та ли вкладка перед нами), каждый менеджер может назвать по своему. Например, "Остатки поставщиков", все равно будет работать.
    BX.ready(function(){
       //обработка открытия вкладки
       BX.addCustomEvent('BX_CRM_INTERFACE_FORM_TAB_SELECTED', BX.delegate(function(self, name, tab_id){
          //вкладка остатков поставщиков
          if (!arTabLoading[tab_id] && self.oTabsMeta[tab_id].name.toLowerCase().indexOf('остатки') !== -1) {
    
          }
       }));
    });


    3.
    Теперь я узнаю дополнительные детали и готовлю контент для вкладки.
    BX.ready(function(){
       //обработка открытия вкладки
       BX.addCustomEvent('BX_CRM_INTERFACE_FORM_TAB_SELECTED', BX.delegate(function(self, name, tab_id){
          //вкладка остатков поставщиков
          if (!arTabLoading[tab_id] && self.oTabsMeta[tab_id].name.toLowerCase().indexOf('остатки') !== -1) {
             var innerTab = BX('inner_tab_'+tab_id),
                dealId = 0, matches = null,
                waiter = BX.showWait(innerTab);
             if (matches = window.location.href.match(/\/crm\/deal\/show\/([\d]+)\//i)) {
                var dealId = parseInt(matches[1]);
             }
             if (dealId > 0) { 
                   arTabLoading[tab_id] = true;
             }
          }
       }));
    });

    Из того, что интересно знать: innerTab - указатель на элемент контента, куда уже можно инсертить контент. dealId - id текущей сделки. И это единственное место, где мы завязываемся на сделку (как видите, парсим URL). Тут вы можете доработать маску или изменить на свою.  И еще, там добавляется пометка в массив arTabLoading, это делается, чтобы при повторном открытии вкладки (без перезагрузки страницы) контент снова не запрашивался. Если вам такое не надо, просто удалите строчку.

    Но контент где-то надо взять. Конкретно в моем случае я делаю запрос на внутренний скрипт посредством того же BX JS. Что отдаст этот скрипт - уже зависит от вашей задачи. У меня выводятся остатки поставщиков по товарам в сделке.
    BX.ajax({
          url: '/ajax/crm_distrib_stores.php',
          method: 'POST',
          dataType: 'html',
          data: {
             id: dealId
          },
          onsuccess: function(data)
          {
             innerTab.innerHTML = data;
             BX.closeWait($this, waiter);
          },
          onfailure: function(data)
          {
             BX.closeWait(innerTab, waiter);
          }
       }
    );

    При обработке ответа вы видите, что я наполняю innerTab. Вот и вся наука. Весь код http://bxapi.ru/code/H6nImTilPRLBTxO/  
katerina
25 Июля 2016 10:55
а можно более подробно для начинающих куда именно мы прописываем эти скрипты?
Вкладку создала, компонент готов, а вот понимания как одно с другим связать отсутствует
Антон Долганин
25 Июля 2016 11:58
Данный скрипт я размещал на странице /crm/deal/index.php во включаемой области.  
Андрей
3 Августа 2016 12:47
Полезный пост! Спасибо
Николай Нагорный
9 Августа 2016 19:37
Спасибо!
Антон, а может Вы вкурсе как добавить кастомную кнопку вот сюда:
http://take.ms/N5QOQ


Сейчас в планах вывести в эту панель кнопку ссылку на веб версию 1с, сама ссылка на обьект у нас есть, осталась кнопка)  
Антон Долганин
10 Августа 2016 4:18
Николай, требовалось туда внедряться как-то. Юзал JS, по другому никак. Обычный jquery - поиск по селектору и внедрение html();

Вообще, внедрение в части CRM посредством JS довольно распространенная практика, так как КП это единая постоянно обновляемая сущность.  
Николай Нагорный
11 Августа 2016 1:04
Спасибо, был вариант номер 1 этот)
Думал может сделали событие при построении тулбара, на примере админского меню
ник
24 Августа 2016 16:46
Антон, а может знаете, каким образом в эти вкладки можно засунуть стандартные компоненты на аяксе типа main.interface.grid, iblock.element.form.add . Если их просто пихнуть в массив через ob_get_contents , то они вылезают в начале сделки, а не во вкладке.
main.interface.grid после перезагрузки вообще влезает  не туда, куда надо.

Если отключить аякс, то всё норм.
Антон Долганин
25 Августа 2016 4:14
Как понял, вы пытаетесь подружить штатный аякс Битрикс (в гриде) с аяксом вкладки. Очень сомневаюсь, что получится избежать глюков. Только если ковырять и отлаживать, а так у меня идей нет.

Есть грубый вариант - обычный iframe :)  его можно рисовать уже при открытии вкладки, и тогда контент тоже динамически подгрузится.
ник
25 Августа 2016 10:04
Спасибо за ответ. К сожалению, как выяснилось, многие компоненты, также не корректно работают из айфрейма. По этим граблям я уже прошёлся :) .
Антон Долганин
25 Августа 2016 11:22
Ответил Максиму ниже - Я бы начал еще анализ с того, что посмотрел с какими параметрами вызываются штатные гриды при отдаче по аякс. Возможно, есть особенность или параметр какой хитрый.
Максим
25 Августа 2016 9:41
Антон, а как же стандартные компоненты работают во вкладках на ajax. Насколько я смотрю по событию которое вы предлагаете обработать происходит запрос к файлу lazyload.ajax.php компонента в котором уже происходит формирование кода компонента с AJAX. Как это реализовать для своего компонента и своей вкладки?
Антон Долганин
25 Августа 2016 11:22
Максим, тут не подскажу, к сожалению. Поэтому и говорю - надо копать.
Я бы начал с того, что посмотрел с какими параметрами вызываются гриды при отдаче по аякс. Возможно, есть особенность или параметр какой хитрый.

В статье пример описан для отдельного аякс-файла, где отдается некоторое содержимое. В моем случае даже не гриды.  
Алексей
23 Марта 2017 11:53
Подскажите, пожалуйста, откуда взялся arTabLoading?
Алексей
23 Марта 2017 11:59
Прошу прощения. Гоню. Слепошара(
Ivan Ivanov
16 Июня 2017 10:59
уж больно костыльный метод.
а есть ли какая то возможность сделать это на стороне кастомизации php шаблонов?
Антон Долганин
16 Июня 2017 11:22
Так там все просто - кастомизируйте шаблон и добавляете. Только не забудьте - вы потеряее все будущие обновления карточки.