Параметр replace

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

По умолчанию Awesomplete подставляет в поле ввода текстовое представление выбранного элемента. Однако при использовании сложных структур данных, кастомных отображений списка или необходимости сохранять отличающееся значение (например, id вместо label), стандартное поведение становится недостаточным. Именно в таких сценариях replace становится ключевым механизмом управления логикой автозаполнения.


Сигнатура и базовое поведение

Функция replace вызывается при выборе элемента из списка и получает один аргумент — выбранный элемент данных:

replace: function (item) {
    this.input.value = item;
}

В простейшем случае item представляет собой строку, и значение напрямую записывается в поле ввода.

Однако Awesomplete поддерживает использование массивов и объектов, поэтому item может быть:

  • строкой
  • массивом [label, value]
  • объектом { label, value }

Поведение по умолчанию

Без переопределения replace библиотека использует встроенную реализацию:

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

При работе с массивами:

["JavaScript", "js"]

в поле ввода попадает первый элемент ("JavaScript"), если не задано иное поведение через item или replace.


Использование с объектами данных

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

Пример структуры данных:

const list = [
    { label: "Germany", value: "DE" },
    { label: "France", value: "FR" }
];

Переопределение replace:

new Awesomplete(input, {
    list: list,
    item: function (text, input) {
        return Awesomplete.$.create("li", {
            innerHTML: text.label
        });
    },
    replace: function (item) {
        this.input.value = item.value;
    }
});

В данном случае:

  • отображается label
  • в input записывается value

Разделение отображения и значения

Основная причина использования replace заключается в необходимости отделить UI-представление от логического значения.

Типичная схема:

  • label — человекочитаемый текст
  • value — идентификатор или код
{
    label: "New York",
    value: 101
}

Без replace в поле ввода попадет весь объект или его строковое представление, что обычно неприемлемо.


Работа с кастомными шаблонами item

Функции item и replace тесно связаны между собой:

  • item отвечает за визуализацию списка
  • replace отвечает за запись выбранного значения

Пример комбинированного использования:

new Awesomplete(input, {
    list: cities,

    item: function (text) {
        const li = document.createElement("li");
        li.innerHTML = `<strong>${text.label}</strong> (${text.country})`;
        return li;
    },

    replace: function (text) {
        this.input.value = text.label;
    }
});

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


Использование с нормализацией данных

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

Пример приведения к верхнему регистру:

replace: function (item) {
    this.input.value = item.label.toUpperCase();
}

Пример удаления пробелов:

replace: function (item) {
    this.input.value = item.label.replace(/\s+/g, "");
}

Интеграция с внешними полями формы

Часто значение, подставляемое через replace, используется не только в input, но и в скрытых полях формы.

replace: function (item) {
    this.input.value = item.label;
    document.querySelector("#countryCode").value = item.value;
}

Таким образом:

  • визуальное поле содержит текст
  • скрытое поле хранит код для отправки на сервер

Работа с асинхронными источниками

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

Пример с API-данными:

fetch("/api/users")
    .then(res => res.json())
    .then(data => {
        new Awesomplete(input, {
            list: data,

            item: function (user) {
                return Awesomplete.$.create("li", {
                    innerHTML: user.name + " (" + user.email + ")"
                });
            },

            replace: function (user) {
                this.input.value = user.name;
            }
        });
    });

Контекст выполнения replace

Функция replace вызывается в контексте экземпляра Awesomplete, что означает доступ к:

  • this.input — DOM-элемент input
  • this.list — текущий список
  • внутренним методам библиотеки

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

replace: function (item) {
    console.log(this.input.id);
    this.input.value = item.label;
}

Отличие replace от других механизмов

Awesomplete предоставляет несколько точек кастомизации, и replace занимает среди них специфическую роль:

  • filter — отвечает за фильтрацию списка
  • sort — управляет порядком элементов
  • item — управляет отображением
  • replace — управляет финальной подстановкой

Таким образом, replace не влияет на список и не участвует в поиске, а срабатывает только на этапе выбора.


Типичные ошибки при использовании

Запись всего объекта в input

replace: function (item) {
    this.input.value = item;
}

Результат: [object Object]


Игнорирование структуры данных

При использовании [label, value]:

replace: function (item) {
    this.input.value = item[1];
}

Если структура изменяется, логика ломается, поэтому предпочтительнее использовать именованные поля.


Несоответствие item и replace

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


Расширенные сценарии использования

Формирование сложных строк

replace: function (item) {
    this.input.value = `${item.city}, ${item.country}`;
}

Использование валидации перед вставкой

replace: function (item) {
    if (item.disabled) return;
    this.input.value = item.label;
}

Запись форматированного значения

replace: function (item) {
    this.input.value = item.label.trim().toLowerCase();
}