Модификация вставляемого значения

Поведение вставки выбранного элемента в поле ввода в Awesomplete определяется двумя ключевыми механизмами: стандартной функцией выбора и пользовательским хук-функционалом, позволяющим перехватывать и изменять значение до момента его установки в input-элемент.

Внутри библиотеки ключевую роль играет метод replace, который отвечает за финальный этап обработки выбранного элемента списка. Именно здесь формируется значение, которое попадёт в текстовое поле.


Базовая логика вставки значения

По умолчанию Awesomplete работает с простым сценарием: при выборе элемента из списка его строковое представление напрямую подставляется в поле ввода.

Упрощённая модель поведения выглядит так:

input.value = suggestion;

Где suggestion — это выбранный элемент массива данных, приведённый к строке.

Однако такой подход ограничен, поскольку не позволяет учитывать сложные структуры данных, форматирование или дополнительные поля.


Хук replace как точка расширения

Основной механизм кастомизации вставки значения — это метод:

Awesomplete.REPLACE

или, в пользовательской конфигурации:

new Awesomplete(input, {
    replace: function(suggestion) {
        this.input.value = suggestion;
    }
});

Функция replace вызывается в момент выбора элемента и полностью контролирует процесс вставки.


Передача структуры данных вместо строки

Awesomplete допускает использование не только строк, но и объектов. В таком случае становится возможной реализация более сложной логики:

const list = [
    { label: "JavaScript", value: "js" },
    { label: "TypeScript", value: "ts" }
];

Без модификации поведения библиотека попытается преобразовать объект в строку, что приведёт к нежелательному результату [object Object].

Для корректной работы применяется переопределение replace:

new Awesomplete(input, {
    list: list,
    replace: function(item) {
        this.input.value = item.value;
    }
});

Разделение отображаемого и вставляемого значений

Ключевая задача модификации вставляемого значения — разделение UI-представления и внутреннего значения формы.

Типичный сценарий:

  • отображается человекочитаемое имя (label)
  • в input записывается технический идентификатор (value)

Пример реализации:

const countries = [
    { label: "Казахстан", value: "KZ" },
    { label: "Россия", value: "RU" },
    { label: "Германия", value: "DE" }
];

new Awesomplete(input, {
    list: countries,
    item: function(text, input) {
        return Awesomplete.ITEM(text.label, input);
    },
    replace: function(item) {
        this.input.value = item.value;
    }
});

В данном случае список отображает названия стран, но форма получает их коды.


Использование функции filter совместно с replace

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

Пример: поиск по нескольким полям объекта

new Awesomplete(input, {
    list: data,
    filter: function(text, input) {
        return (
            text.label.toLowerCase().includes(input.toLowerCase()) ||
            text.code.toLowerCase().includes(input.toLowerCase())
        );
    },
    replace: function(item) {
        this.input.value = item.code;
    }
});

Здесь фильтрация работает по двум полям, а вставка ограничивается одним.


Нормализация значения перед вставкой

Часто требуется не просто подставить поле объекта, а дополнительно обработать его:

  • привести к нижнему регистру
  • удалить пробелы
  • форматировать строку
  • добавить префикс или суффикс

Пример нормализации:

new Awesomplete(input, {
    list: users,
    replace: function(item) {
        let value = item.username.trim().toLowerCase();
        this.input.value = "@" + value;
    }
});

Такой подход используется при реализации упоминаний пользователей, тегов и поисковых команд.


Использование составных значений

В некоторых случаях в input требуется вставить составное значение, основанное на нескольких полях.

Пример:

new Awesomplete(input, {
    list: employees,
    replace: function(item) {
        this.input.value = item.name + " <" + item.email + ">";
    }
});

Такой формат полезен для:

  • CRM-систем
  • выбора контактов
  • административных панелей

Интеграция с форматированием ввода

При сложной логике ввода replace часто связывается с внешними форматтерами.

Пример: автоматическое добавление разделителей

new Awesomplete(input, {
    list: tags,
    replace: function(item) {
        const current = this.input.value.split(",");
        current[current.length - 1] = item.name;
        this.input.value = current.join(",") + ",";
    }
});

В этом сценарии Awesomplete используется как инструмент вставки элементов в список тегов.


Защита от нежелательных значений

Модификация вставки также позволяет реализовать контроль допустимых значений.

Пример проверки:

new Awesomplete(input, {
    list: products,
    replace: function(item) {
        if (!item || !item.id) return;

        this.input.value = item.id;
    }
});

Это предотвращает вставку некорректных данных, особенно при асинхронной подгрузке списка.


Взаимодействие с событием выбора

Хотя replace управляет значением, часто он используется вместе с обработчиком awesomplete-selectcomplete.

Пример комбинированного поведения:

input.addEventListener("awesomplete-selectcomplete", function(e) {
    console.log("Выбран элемент:", e.text);
});

При этом replace уже сформировал финальное значение, а событие позволяет реагировать на результат.


Программное переопределение логики вставки

В более сложных сценариях replace может быть заменён динамически:

const aw = new Awesomplete(input, {
    list: data
});

aw.replace = function(item) {
    this.input.value = JSON.stringify(item);
};

Такой подход используется при отладке или работе с универсальными структурами данных.


Условная вставка значений

Модификация может зависеть от состояния интерфейса или внешних факторов:

new Awesomplete(input, {
    list: items,
    replace: function(item) {
        if (this.input.dataset.mode === "id") {
            this.input.value = item.id;
        } else {
            this.input.value = item.name;
        }
    }
});

Это позволяет одному автокомплиту обслуживать разные сценарии использования без изменения списка данных.


Использование вычисляемых значений

Иногда вставляемое значение формируется не из данных напрямую, а вычисляется:

new Awesomplete(input, {
    list: products,
    replace: function(item) {
        const discounted = item.price * 0.9;
        this.input.value = item.name + " - " + discounted.toFixed(2);
    }
});

Такой подход встречается в интерфейсах с динамическими параметрами.


Контроль форматирования через внешний контекст

Replace может использовать внешние переменные приложения:

const currency = "USD";

new Awesomplete(input, {
    list: products,
    replace: function(item) {
        this.input.value = item.name + " (" + item.price + " " + currency + ")";
    }
});

Это позволяет централизованно управлять форматом без изменения структуры данных.


Ограничения механизма replace

Несмотря на гибкость, механизм имеет ряд особенностей:

  • полностью заменяет стандартную вставку
  • требует ручного контроля всех сценариев форматирования
  • может конфликтовать с внешними обработчиками input
  • не выполняет автоматическую сериализацию объектов

Поэтому при сложной логике часто используется комбинация item, filter и replace вместо одного только хука вставки.


Комбинирование с кастомным item-рендерингом

При кастомном отображении списка важно сохранять согласованность с replace:

new Awesomplete(input, {
    list: items,
    item: function(text) {
        return Awesomplete.ITEM(text.name, text.query);
    },
    replace: function(item) {
        this.input.value = item.query;
    }
});

Несоответствие между визуальным элементом и вставляемым значением может приводить к логическим ошибкам интерфейса.