Перейти к содержанию

Правка карточки CRM

Иногда надо поправить отображение какого-либо поля в карточке CRM (Lead, Deal).

Можно использовать события:

  • onBeforeGetPublicView
  • onBeforeGetPublicEdit
  • onAfterGetPublicView
  • onAfterGetPublicEdit

Механизм работы

Описан тут: CUserTypeManager::GetPublicEdit

  • Событие onBeforeGetPublicEdit, которое должно вернуть \Bitrix\Main\EventResult::SUCCESS с параметром $html
  • если $html === null, то ищем $arUserField['EDIT_CALLBACK'] типа callable
  • иначе ищем $arType['EDIT_CALLBACK'] типа callable
  • иначе ищем $arUserField['EDIT_COMPONENT_NAME'] и вызываем такой компонент
  • иначе ищем $arType['EDIT_COMPONENT_NAME'] и вызываем такой компонент
  • иначе вызываем стандартный компонент bitrix:system.field.edit

Обратить внимание

CUserTypeManager::GetPublicView — метод вызывается для показа значения в CRM

onGetPublicEdit

Данное событие вызывается перед формированием html кода для редактирования свойства. Обработчик должен вернуть объект \Bitrix\Main\EventResult:

use Bitrix\Main\EventResult;

AddEventHandler('main', 'onGetPublicEdit', function ($field, $form) {
    if ($form['CONTEXT'] === 'UI_EDITOR' && $field['FIELD_NAME'] === 'UF_MY_PROPERTY') {
        $html = '<h3>html код для отображения свойства</h3>';
        return new EventResult(EventResult::SUCCESS, $html, 'main');
    }
});

Для формирования html удобно использовать компонент. Используя компонент, можно подключать script.js и добавлять интерактивность при редактировании свойства.

use Bitrix\Main\EventResult;

AddEventHandler('main', 'onGetPublicEdit', function ($field, $form) {
    if ($form['CONTEXT'] === 'UI_EDITOR' && $field['FIELD_NAME'] === 'UF_MY_PROPERTY') {
        ob_start();
        $APPLICATION->IncludeComponent(
            'vendor:my.property.edit',
            ''
            [
                'FIELD' => $field,
                'FORM'  => $form,
            ],
            null,
            ['HIDE_ICONS' => 'Y']
        );
        $html = ob_get_clean();
        return new EventResult(EventResult::SUCCESS, $html, 'main');
    }
});

Пример шаблона компонента:

<div>
    <h4>Моё свойство</h4>
    <input
        name="<?= $arParams['FIELD']['FIELD_NAME']; ?>"
        value="<?= $arParams['FIELD']['VALUE']; ?>"
    >
</div>

Обратить внимание

Для формы редактирования свойства необходимо выводить <input name=""> с правильным трибутом name, иначе значение перестанет пересохраняться.

Работа на фронте

  • Получение значения поля
    BX.Crm.EntityEditor.getDefault().getControlById('CLIENT');
    

События на фронте

  • onControlChanged - бросают все: И EntityEditorColumn, и EntityEditorSection, и EntityEditorUserField. Различить можно по полю _id в первом параметре
    BX.addCustomEvent('onControlChanged', (entityEditorField, params) => {
        if (entityEditorField._id === 'UF_MY_CUSTOM_FIELD') {
            const typeId = params.control.getContentWrapper().querySelector('[name=UF_MY_CUSTOM_FIELD]')?.value ?? '';
            console.log(typeId);
        }
    });
    
  • BX.Crm.EntityEditor:onControlChange

Оба события срабатывают в BX.Crm.EntityEditorSection.notifyChanged (bitrix/js/ui/entity-editor/js/control.js)

Control

Контролы могут быть в разных режимах: Edit, View.

control.isInViewMode();
control.isInEditMode();
control.getMode() === BX.UI.EntityEditorMode.view;

Во View режиме значение просто так не достать, по крайней мере для UF_* свойств. У контрола есть метод getRuntimeValue, но для UF_* он возвращает пустую строку.

let fieldValue;
if (control.isInEditMode()) {
    fieldValue = control.getContentWrapper().querySelector('[name=UF_MY_CUSTOM_FIELD]')?.value ?? '';
} else {
  fieldValue = control.getFieldValue();
}

Блокирование полей CRM карточки

У объекта BX.UI.EntitySchemeElement есть поле _isEditable, которое считывается при переключении режима. Поле инициализируется из значения editable в конструкторе.

Через result_modifier компонента bitrix:crm.entity.editor можно управлять этим значением:

/bitrix/components/bitrix/crm.entity.editor/templates/.default/result_modifier.php
if ($arResult['ENTITY_TYPE_NAME'] === 'DEAL') {
    foreach ($arResult['ENTITY_SCHEME'] as &$columnElement) {
        foreach ($columnElement['elements'] as &$sectionElement) {
            foreach ($sectionElement['elements'] as &$field) {
                $field['editable'] = /* Логика того, доступно ли поле для редактирования */;
            }
        }
    }
}