Документация

Своя функция обновления данных (setUpdateFunction)

Список сохраняет правку строки методом сущности update(). Не всякая сущность умеет это делать: Bitrix\Iblock\ElementTable, например, не даёт изменять элемент напрямую — у инфоблоков своё API со свойствами, правами и переиндексацией.

Для таких случаев в контроллере переопределяют updateEntityRow().

php · ElementList.php
use Bitrix\Main;
use Bitrix\Main\ORM;

protected function updateEntityRow(array $primary, $row): ORM\Data\UpdateResult
{
    $result = new ORM\Data\UpdateResult();

    $element = new \CIBlockElement();

    if (!$element->Update($primary['ID'], $row)) {
        $result->addError(new Main\Error($element->LAST_ERROR));
    }

    return $result;
}

Метод получает первичный ключ строки и массив изменённых полей, а возвращает Bitrix\Main\ORM\Data\UpdateResult. Ошибки, добавленные в результат, список покажет рядом со строкой — придумывать свой вывод сообщений не нужно.

Удаление

Так же переопределяется удаление — deleteEntityRow():

php
protected function deleteEntityRow($primary): ORM\Data\DeleteResult
{
    $result = new ORM\Data\DeleteResult();

    if (!\CIBlockElement::Delete($primary['ID'])) {
        $result->addError(new Main\Error('Не удалось удалить элемент'));
    }

    return $result;
}

Что было раньше

В старом API то же делалось функциями обратного вызова:

php · было.php
$list->setUpdateFunction(function ($ID, $arFields) {
    $result = new \Bitrix\Main\Entity\UpdateResult();
    // …
    return $result;
});

Разница не только в записи. Метод контроллера видит всё состояние списка — сущность, права, настройки — и может позвать другие методы, а замыкание получало только идентификатор и поля.