K4:DropDownMapper
From In-Portal Developers Guide
| ||
---|---|---|
Статьи в этой категории | ||
|
В статье о JavaScript
классе AjaxDropdownPreloader, рассматривалось взаимодействие между двумя ВМ:
По мере необходимости возможно подключить любое количество зависимых ВМ, причем каждое новое зависимое ВМ означает создание нового объекта класса AjaxDropdownPreloader. Сложность кода будет расти и логика становиться менее прозрачной. В результате выгода от использования AjaxDropdownPreloader становится спорной.
Класс AjaxDropdownPreloader является оптимальным решением только в случае использования с двумя ВМ (главным - зависимым). А рассматриваемый в данной статье JavaScript
класс DropDownMapper
специально создан для реализации связи между тремя и более ВМ. Класс DropDownMapper
реализует связь между множеством ВМ, используя массив экземпляров класса AjaxDropdownPreloader.
Contents |
Параметры инициализации
Для успешной реализации связи между многими ВМ необходимо создать экземпляр класса DropDownMapper
, передав ему параметры, описанные в приведённой ниже таблице.
название | описание |
---|---|
map (object)
|
Данный параметр представляет из себя 'UniqueKey' : { 'Field' : 'FieldName', 'Pass' : [<field_names>], 'Value' : 'SelectedValue', 'Dependent' : false, 'SubNodes' : { } }
|
request (string)
| Ссылка, при заходе на которую будет возвращён XML документ, содержащий новый набор опций для зависимого ВМ. XML документ должен быть в следующем формате:
<field_options> <option>ID1</option> <option>ID2</option> </field_options> Стоит обратить особое внимание на то, что XML документ содержит только |
input_mask (string)
| Маска для получения любого элемента ввода на форме. Обычно маска получается путём вызова тэга InputName со значением "#FIELD_NAME# " в качестве названия поля объекта:
<inp2:prefix_InputName field="#FIELD_NAME#"/>
// вернёт строку вида: prefix[ID][#FIELD_NAME#] |
Настройка шаблона редактирования
Для подключения класса DropDownMapper
на форму достаточно получить его экземпляр с правильно переданными параметрами, в одном из которых и нужно определить зависимость между множеством ВМ. Для примера рассматривается ситуация, в которой ВМ от полей Field_11
и Field_12
зависят от значения поля Field_1
, а ВМ Field_111
зависит от значения поля Field_11
.
После выполнения приведённых ниже шагов настройку шаблона можно считать завершённой.
- Добавить на форме элементы ВМ:
<inp2:m_RenderElement name="inp_edit_options" prefix="sample-prefix" field="Field_1" title="la_fld_Field_1"/> <inp2:m_RenderElement name="inp_edit_options" prefix="sample-prefix" field="Field_11" title="la_fld_Field_11"/> <inp2:m_RenderElement name="inp_edit_options" prefix="sample-prefix" field="Field_12" title="la_fld_Field_12"/> <inp2:m_RenderElement name="inp_edit_options" prefix="sample-prefix" field="Field_111" title="la_fld_Field_111"/>
- Добавить вызов класса
DropDownMapper
передав ему все требуемые параметры:
var $mapping = { 'Level_1' : { 'Field' : 'Field_1', 'Dependent' : false, 'SubNodes' : { 'Level_11' : { 'Field' : 'Field_11', 'SubNodes' : { 'Level_111' : { 'Field' : 'Field_111' } } }, 'Level_12' : { 'Field' : 'Field_12' } } } }; new DropDownMapper( $mapping, '<inp2:m_Link template="dummy" pass="m,sample-prefix" sample-prefix_event="OnGetDropDownXML" q="#QUESTIONED#" f="#FILTERS#" no_amp="1"/>', '<inp2:sample-prefix_InputName field="#FIELD_NAME#"/>' );
Настройка обработчика событий
В метод OnGetDropDownXML
необходимо добавить функциональность для получения опций ВМ каждого конкретного случая:
/** * [AJAX] Метод для получения отфильтрованных опций в виде XML документа. * * @param kEvent $event */ function OnGetDropDownXML(&$event) { $event->status = erSTOP; if ($this->Application->GetVar('ajax') != 'yes') { return ; } // $q поле соотвествующие зависимому ВМ, для которого в данный момент вычисляются опции. $q = $this->Application->GetVar('q'); $f = $this->Application->GetVar('f'); parse_str($f, $filters); // $filters массив, где ключи это поля соответствующих ВМ, а значения выбранные опции из соответствующих ВМ // Все необходимые фильтры для SQL запроса в массиве $filters // Ниже требуется составить SQL для каждого конкретного случая switch ($q) { case 'Field_12': $sql = 'SELECT ... FROM ... WHERE ...'; break; case 'Field_11': $sql = 'SELECT ... FROM ... WHERE ...'; break; case 'Field_111': $sql = 'SELECT ... FROM ... WHERE ...'; break; } if (!$sql) { return ; } $data = $this->Conn->Query($sql); if (!$data) { return ; } $o = ''; foreach ($data as $row) { $attributes = ''; foreach ($row as $field => $value) { if ($field == 'Value' || $field == 'Name') { continue; } $attributes .= $field . '="' . htmlspecialchars($value) . '" '; } $o .= '<option value="' . htmlspecialchars($row['Value']) . '" ' . $attributes .'><![CDATA[' . $row['Name'] . ']]></option>'; } $this->Application->XMLHeader(); echo '<field_options>' . $o . '</field_options>'; }
Событие OnGetDropDownXML
необходимо добавить в метод mapPermissions, который обеспечит проверку наличия у пользователя необходимых прав доступа для вызова данного события:
/** * Метод связывающий события и права, необходимые для их выполнения. * */ function mapPermissions() { parent::mapPermissions(); $permissions = Array ( 'OnGetDropDownXML' => Array ('self' => true), ); $this->permMapping = array_merge($this->permMapping, $permissions); }
Также следует обратить внимание на некоторые, описанные ниже, приёмы, которые использовались при написании события OnGetDropDownXML .
|
- В начале события рекомендуется установить статус его выполнения в erSTOP. Это укажет на то, что по окончания выполнения события не нужно показывать содержание переданного шаблона (в данном случае это "
dummy
"):
$event->status = erSTOP;
- В начале события написать код, который позволит игнорировать запросы, которые будут делать поисковые системы:
if ($this->Application->GetVar('ajax') != 'yes') { return ; }
Параметр "ajax
" добавляется автоматически при отправлении каждого AJAX запроса. Если поисковая система где-то найдёт ссылку, в которой указано данное событие, то зайдя на неё тело события выполнено не будет.
- Перед выводом XML документа на экран необходимо послать браузеру соответствующий заголовок. Сделать это можно при помощи метода
Application::XMLHeader
:
$this->Application->XMLHeader();