Связанный выбор JForm Joomla с внешним ключом, Ajax и jQuery

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

У меня есть 2 таблицы: Manufacturer и Model

Обе таблицы проиндексированы столбцом id, а таблица Model имеет внешний ключ, связанный со столбцом id производителя.

В настоящее время поля выбора представляют собой поля типа JForm "sql", которые имеют запрос в xml для извлечения всех моделей из базы данных.

Я знаю, что мне нужно добавить функцию для получения значений модели на основе производителя в контроллере и вызвать ее с помощью AJAX с POST (используя «task = myFunction»). Я просто не могу придумать, как вернуть возвращаемые значения обратно в JForm, чтобы функция getInput могла создать на их основе поле выбора.

Я видел плагины jQuery, которые просто фильтруют модель на основе ранее выбранного поля, но это похоже на мошенничество, и я хотел бы сделать это «правильным» способом.

Большое спасибо


person mousebat    schedule 01.08.2013    source источник


Ответы (2)


Чтобы ответить на мой собственный вопрос...

Я создал пользовательское поле формы на основе стандартного поля формы joomla типа «SQL».

В пользовательское поле формы я добавил jQuery/AJAX, который после изменения этого родительского поля выбора принимает выбранное значение, добавляет его к запросу ajax $_GET и вызывает задачу в субконтроллере. Затем субконтроллер получает выбранное значение из jinput и передает его методу в модели, который использует его для возврата данных JSON для поля child.

Я не знал об этом, когда спрашивал, но Joomla использует плагин jQuery Chosen, чтобы скрыть стандартные HTML-списки выбора болота и создать вместо них красивые живые выпадающие списки с возможностью поиска. Также я только что заметил, что joomla 3.1 теперь включает плагин Ajax Chosen, но у меня такое чувство, что его реализация предназначена только для тегов? Может быть, кто-то может пролить свет на это?

Функция getOptions пользовательского поля выглядит примерно так:

protected function getOptions()
{
    // Build the script.
    $script = array();
    $script[] = 'jQuery(document).ready(function() {                                                                            ';
    $script[] = '   jQuery("#jform_child").trigger("liszt:updated");                                                            ';
    $script[] = '   jQuery("#jform_parent").chosen().change( function() {                                                       ';
    $script[] = '       var selectedValue = jQuery("#jform_parent").val();                                                      ';
    $script[] = '       jQuery.ajax({                                                                                           ';
    $script[] = '           type: "GET",                                                                                        ';
    $script[] = '           dataType: "json",                                                                                   ';
    $script[] = '           url: "index.php?option=com_mycomponent&task=myview.controllerTask",                         ';
    $script[] = '           data: {                                                                                             ';
    $script[] = '               "selectedValue": selectedValue                                                                  ';
    $script[] = '           },                                                                                                  ';
    $script[] = '           success:function(data) {                                                                            ';
    $script[] = '               jQuery("select#jform_child option").remove();                                                   ';
    $script[] = '               jQuery.each(data, function(i, item) {                                                           ';
    $script[] = '                   jQuery("select#jform_child").append( "<option value="+ i +">" + item + "</option>" );       ';
    $script[] = '               });                                                                                             ';
    $script[] = '               jQuery("select").trigger("liszt:updated");                                                      ';
    $script[] = '           }                                                                                                   ';
    $script[] = '       });                                                                                                     ';
    $script[] = '   });                                                                                                         ';
    $script[] = '});                                                                                                            ';

    // Add the script to the document head.
    JFactory::getDocument()->addScriptDeclaration(implode("\n", $script));

    $options = array();

    // Initialize some field attributes.
    $key = $this->element['key_field'] ? (string) $this->element['key_field'] : 'value';
    $value = $this->element['value_field'] ? (string) $this->element['value_field'] : (string) $this->element['name'];
    $translate = $this->element['translate'] ? (string) $this->element['translate'] : false;
    $query = (string) $this->element['query'];

    // Get the database object.
    $db = JFactory::getDbo();

    // Set the query and get the result list.
    $db->setQuery($query);
    $items = $db->loadObjectlist();

    // Build the field options.
    if (!empty($items))
    {
        foreach ($items as $item)
        {
            if ($translate == true)
            {
                $options[] = JHtml::_('select.option', $item->$key, JText::_($item->$value));
            }
            else
            {
                $options[] = JHtml::_('select.option', $item->$key, $item->$value);
            }
        }
    }

    // Merge any additional options in the XML definition.
    $options = array_merge(parent::getOptions(), $options);

    return $options;
}

Как видите, jQuery удаляет текущие параметры выбора из дочернего поля и заполняет его новыми параметрами, полученными из субконтроллера. Выбранное значение родительского поля выбора передается субконтроллеру в виде переменной "selectedValue" data: { }. Как только новые параметры заполнены, мы вызываем .trigger("liszt:updated") в дочернем поле, это заставит плагин Chosen перестроить меню выбора с новыми параметрами.

В любом случае - вот задача субконтроллера:

public function controllerTask()
{
    JFactory::getDocument()->setMimeEncoding( 'application/json' );
    JResponse::setHeader('Content-Disposition','attachment;filename="progress-report-results.json"');

    $jinput = JFactory::getApplication()->input;
    $selectedValue = $jinput->get('selectedValue');
    $model = $this->getModel();
    echo json_encode($model->modelMethod($selectedValue));

    JFactory::getApplication()->close();
}

Он берет переменную «selectedValue», которую мы передали с помощью Ajax, и использует ее с помощью метода modelMethod. В нашем случае modelMethod принимает переменную «selectedValue» и возвращает список дочерних данных, которые будут отображаться в дочернем поле.

Вот этот метод модели:

public function modelMethod($selectedValue) {
    $db = JFactory::getDbo();
    $db->setQuery("SELECT 0 AS `id`, '- Please select a child -' AS `child` UNION SELECT id, child FROM #__mycomponent_children WHERE #__mycomponent_children.parent = " . $selectedValue);
    $list = $db->loadObjectList();
    foreach ($list as $option) {
        $options[$option->id] = $option->child;
    }
    return $options;
}

Я надеюсь, что это поможет кому-то!

person mousebat    schedule 06.08.2013

Сначала создайте группу плагинов в соответствии с вашими потребностями, например: content, затем в вашем плагине/модуле метод/событие, возвращающее данные.

Пример для content:

BASE / index.php?option=com_ajax&plugin=manufacturer&format=raw&group=content

Связанный вопрос

person Eilluj    schedule 09.03.2016