Справка

Фильтрация элементов

Облачный Pyrus
Безоблачный Pyrus

Скрипты позволяют ограничивать список доступных вариантов значений для полей типа Справочник или Форма. Для этого необходимо подписаться на изменение необходимых полей формы через onChange и вызвать одну из функций установки фильтра: setFilter или setFilterAsync.

Фильтрация элементов справочника

При работе с полем Справочник функция фильтрации должна вернуть объект с полем values, содержащим список значений первой колонки справочника.

interface form {
    onChange(
        fieldNames: string[],
        executeOnLoad: boolean = false
    ): ChangeHandler
}

interface ChangeHandler {
    setFilter(
        fieldName: string,
        calcFilter: (state: FormState) => {
            values: string[]
        } | null
    )
    setFilterAsync(
        fieldName: string,
        calcFilterAsync: (state: FormState) => Promise<{
            values: string[]
        } | null>
    )
}

Рассмотрим пример: когда оператор выбирает в форме регион, в поле Город должны быть доступны только города из этого региона, а не общий список городов.

В этом примере полю Регион соответствует справочник Регионы, а полю Город — справочник Города. Города и регионы связаны между собой в отдельном справочнике Города по регионам.

Чтобы фильтровать список городов по выбранному региону, добавим в скрипты формы следующий блок кода:

const catalogPromise = form.getCatalog("Города по регионам");

             // ↓ Название поля со справочником «Регионы»
form.onChange(["Регион"])
                // ↓ Название поля со справочником «Города»
  .setFilterAsync("Город", async state => {

    const [region] = state.changes;

    const catalogItems = await catalogPromise;

    if (!catalogItems || !region?.columns)
      return null;

    // Получаем значение колонки «Регион» из выбранного
    // элемента справочника «Регионы»
    const regionCol = region.columns["Регион"];

    const filtered = catalogItems
        // Фильтруем элементы справочника «Города по регионам»,
        // оставляя только относящиеся к выбранному региону
        .filter(item => item.columns["Регион"] === regionCol)
        // Создаем массив названий городов
        .map(item => item.columns["Город"]);

    /*
     * В переменной filtered сохранится список городов выбранного региона.
     * Например, для региона «Тульская область»:
     * ["Алексин", "Богородицк", "Тула", ...]
     *
     * Это ключи для фильтрации справочника «Города» (поле «Город»),
     * соответствующие первой (ключевой) колонке данного справочника.
     */

    return filtered.length > 0
        ? { values: filtered }
        : null
});

Фильтрация в поле типа Форма

Для ограничения списка вариантов значений в поле типа Форма функция фильтрации должна вернуть объект с полем filters, содержащим список условий фильтрации по значениям полей связанной формы.

interface form {
    onChange(
        fieldNames: string[],
        executeOnLoad: boolean = false
    ): ChangeHandler
}

interface ChangeHandler {
    setFilter(
        fieldName: string,
        calcFilter: (state: FormState) => {
            filters?: FormLinkFilter[]
        } | null
    )
    setFilterAsync(
        fieldName: string,
        calcFilterAsync: (state: FormState) => Promise<{
            filters?: FormLinkFilter[]
        } | null>
    )
}

interface FormLinkFilter {
    fieldId?: number;
    fieldName?: string;
    fieldCode?: string;
    value: FieldValue;
}

Каждое условие фильтрации FormLinkFilter включает идентификатор поля связанной формы (fieldId или fieldName или fieldCode) и значение поля.

Рассмотрим пример: при изменении поля «manager» будем фильтровать список задач в поле «contragent», показывая только те задачи связанной формы, в которых в поле «Менеджер» указан тот же пользователь, что и в поле «manager» исходной формы.

form.onChange(["manager"], true)
  .setFilter("contragent", state => {
    const [manager] = state.changes;

    if (!manager?.person_id) return null;

    return {
      filters: [{
        fieldName: "Менеджер",
        value: manager.person_id
      }]
    }
  });

Была ли эта статья полезной?