Ввод с подсказкой
Содержание |
suggest — особый тип поля ввода. Он сочетает в себе черты, присущие как строковому полю (string), так и списку выбора (select). По этой причине одному полю типа suggest с именем $name соответствует не 1, а целых 2 параметра запроса:
- "_${name}__label"
- введённое строковое значение;
- "_${name}__id"
- выбранный id;
Строго говоря, на момент написания этого текста параметров даже 3, но последний ("_${name}" со значением, дублирующим "_${name}__label") рассматривается как неподдерживаемый. При использовании suggest-полей значение "_${name}" должно уточняться в процедуре проверки данных.
В любом случае suggest-полю соответствует не текстовый столбец данных (varchar), а ссылка.
Параметры описания поля
В основном (за исключением опции size) описание suggest почти копирует таковое для select:
{ name => 'id_voc_goods', label => 'Что', type => 'suggest', size => 60, values => sub {sql (voc_goods => [ 'id', ['label LIKE ?%' => $_REQUEST {_id_voc_goods__label}], [LIMIT => [15]], ])}, href => "/?type=voc_goods&id=$data->{id_voc_goods}", },
Однако, как легко видеть, в качестве списка значений (values) здесь фигурирует код. Вообще говоря, это может быть ссылка на любую подпрограмму, возвращающую массив хэшей с компонентами id и label. Удобнее всего, как в данном примере, использовать анонимную процедуру на базе sql.
Рассмотрим более подробно обстоятельства вызова данной процедуры.
Режим редактирования
Когда поле получает фокус ввода, а также при каждом изменении его значения данная процедура вызывается таким образом, что ей доступен хэш %_REQUEST с актуальным содержимым всех полей формы, кроме id (в действительности для этого выполняется реальный submit с дополнительным параметром __suggest — при этом действия не производится, хотя параметр action присутствует).
В большинстве случаев (как в нашем примере) параметр "_${name}__label" должен использоваться для фильтрации множества показываемых записей, как правило, в LIKE-фильтре.
Использование suggest уместно в тех случаях, когда select не подходит из-за необозримой величины полного списка значений, так что всегда имеет смысл позаботиться о явном ограничителе выборки в виде псевдофильтра LIMIT.
Режим просмотра
Если поле типа suggest превращается в static, то отображаемая строка вычисляется как поле label первой (она должна быть едиственной) записи выборки, сформированной той же процедурой values при установленном $_REQUEST {id}, соответствующем значению поля.
В большинстве случаев это достигается включением строки 'id' в список фильтров sql.
Варианты применения
Выбор из фиксированного справочника
Поле suggest можно использовать в режиме "бесконечного select" для таких справочников, как, скажем, пользователи, контрагенты и т. п., если их многие десятки.
При этом текстовое поле применяется исключетельно для поиска, а смысл имеет параметр "_${name}__id". Небудем забывать, что ссылочное поле в таблице данных называется просто $name, и именно к такое имя предполагают процедуры API. Соответственно, валидатор должен содержать фрагмент вида:
$_REQUEST {$name} = $_REQUEST {"_${name}__id"} or return "#_${name}#:Вы забыли...";
Расширяемый справочник
Теперь обратимся к тому случаю, когда допустимо расширение справочника прямо с формы ввода. То есть строка, не обнаруженная в списке, может быть немедленно добавлена в него. При этом необходимо явно разделять и по-разному обрабатывать 2 варианта: выбор существующего значения и добавление нового. Вот пример из реального приложения, где выбирается значение ссылки id_voc_goods на справочник товаров voc_goods:
if ($_REQUEST {_id_voc_goods__id}) { $_REQUEST {_id_voc_goods} = $_REQUEST {_id_voc_goods__id}; } else { $_REQUEST {_id_voc_goods__label} or return "#_id_voc_goods#:Вы забыли назвать товар"; $_REQUEST {_id_voc_goods} = sql_do_insert (voc_goods => { fake => 0, label => $_REQUEST {_id_voc_goods__label}, }); }
Ограничения
Поскольку, как упоминалось выше, при каждом редактировании текста в поле производится submit всей формы, крайне не рекомендуется совмещать поля типов suggest и file.
Поле типа suggest может использоваться в качестве дочернего для сложного radio, однако в этом случае, вероятно, возникнут проблемы, связанные с тем, что при обновлении списка строк draw_form будет (виртуально) отрисовываться с невидимым suggest, и список в результате останется пустым. В таком случае необходимо определять режим показа формы по значению $_REQUEST {__suggest} и, если оно непусто, то выдавать упрощённую форму с единственным полем.