Сложная форма с выбором относительных параметров и вывода результата в Ajax

Главные вкладки

Аватар пользователя andem andem 16 октября 2016 в 17:49

Хочу сделать форму для сайта по заправки картриджей.
Необходимо чтобы посетитель заполнил зависимые поля Принтер>Серия>модель>картридж и на основе этих данных ниже через ajax при нажатии кнопки вывелось ему стоимость заправки выбранного картриджа.
Каждое последующее поле списка, должно содержать данные относительно выбранного предыдущего.
Не понимаю как это реализовать. Какие способы и методы выбрать. Направьте пожалуйста.

Комментарии

Аватар пользователя andem andem 18 октября 2016 в 20:14

Огромное спасибо за примеры! Многое теперь стало доступно. Но к сожалению моего случая там нет((

Аватар пользователя andem andem 18 октября 2016 в 20:15

Спасибо. Ajax в моей форме уж точно будет. Да и без него реализовать обновление второго селлекта никак.

Аватар пользователя andem andem 18 октября 2016 в 20:19

По ссылке совсем не то. Там последовательно показывающиеся элементы формы. А мне нужно чтобы от выбранного первого селекта (Родительский термин таксономии) менялся второй селект (с дочерними терминами таксономии выбранного родительского термина). Потом после выбора во втором селекте, в третьем уже подгружались соответствующие заголовки нод. И потом при нажатии сабмита, это все дело подсчитывалось и аджаксом выводилось значение (или значение полей ноды).

Аватар пользователя mbaev mbaev 18 октября 2016 в 20:27

Ну ровно то, что вам нужно никто не разжуёт и не положит в рот. По ссылке концепт работы формы через ajax. Какую логику туда засунуть - дело ваше.

Аватар пользователя andem andem 18 октября 2016 в 20:30

да, дело в том, что мне не нужно разжовывать. Я просто уперся в стену и не могу продвинутся. Не могу получить значение. Пробую брать переменную $form_state['values']['field_select']. А она пустая постоянно(

Аватар пользователя andem andem 18 октября 2016 в 20:32

Уфф... Парни. Не делал еще ниразу модули и с form API тоже. Решил все это изучить. Вроде получается но появилась загвоздка. Первый селект кое как вывел. А вот после введенного значения получить id таксономии для второго и подставить варианты его дочерних, что то не могу догнать.
Оочень нужна ваша помощь. Вот мой код:

<?php
/**
 * Создаю страницу формы
 */
 
function Mymodule_menu() {
     
$items = array();
     
$items['Mymodule'] = array(
         
'title' => 'Form API',
         
'page callback' => 'drupal_get_form',
         
'page arguments' => array('Mymodule_form'),
         
'access callback' => TRUE
         
);
         return 
$items;
 }
/**
 * Реализация hook_form() Создаем форму
 */
 
function Mymodule_form() {
    
$vid 2// id словаря таксономии
    
$parent taxonomy_get_tree($vid01);
    
    
$form['field_select'] = array(
        
'#prefix' => '<div id="wrappp">',
        
'#suffix' => '</div>',
      
'#type' => 'select',                                  
      
'#title' => t('Селект'), 
      
'#ajax' => array(                         
          
'callback' => 'reload_selekt_ajax_callback'
          
'wrapper' => 'wrappp',   
          ),
    );
    foreach (
$parent as $key => $val) {
         
$form['field_select']['#options'][] = $val->name;
       }
       
    
// Описал кнопку отправки форму
    
$form['submit'] = array(
      
'#type' => 'submit',                      
      
'#value' => t('отправить форму'),         
      
'#ajax' => array(                         
          
'callback' => 'Mymodule_ajax_callback'
          
'wrapper' => 'Mymodule-form'
          
'event' => 'click',
          ),
    );
    return 
$form;
 }
/**
 * Реализация hook_ajax_callback()
 */
 
function Mymodule_ajax_callback($form, &$form_state) {
    return 
$form
 }
  function 
reload_selekt_ajax_callback($form, &$form_state) {
    return 
$form['field_select']; 
 }
?>
 
Аватар пользователя mbaev mbaev 18 октября 2016 в 22:03
1

Получите, распишитесь.

<?php
/**
 * Создаю страницу формы
 */
function mymodule_menu() {
  
$items = array();
  
$items['mymodule'] = array(
    
'title'           => 'Form API',
    
'page callback'   => 'drupal_get_form',
    
'page arguments'  => array('mymodule_form'),
    
'access callback' => TRUE,
  );
  return 
$items;
}

/**
 * Form builder for mymodule.
 */
function mymodule_form($form, &$form_state) {
  
$form['#wrapper_id'] = drupal_clean_css_identifier(__FUNCTION__) . '-wrapper';
  
$form['#prefix'] = "<div id='{$form['#wrapper_id']}'>";
  
$form['#suffix'] = "</div>";

  

// id словаря таксономии;
  
$vid 15;

  

$form['select_wrapper'] = array(
    
'#type'        => 'fieldset',
    
'#title'       => t('Select wrapper'),
    
'#description' => t('Select wrapper'),
    
'#collapsible' => TRUE,
    
'#collapsed'   => FALSE,
    
'#tree'        => TRUE
  
);

  

$tree taxonomy_get_tree($vid01);

  

$tree array_map('get_object_vars'$tree);
  
$tids array_column($tree'tid');
  
$term_names array_column($tree'name');
  
  
$form['select_wrapper'][0] = array(
    
'#type'    => 'select',
    
'#title'   => 'Селект для термина 0',
    
'#options' => array_combine($tids$term_names),
    
'#weight'  => 0,
    
'#ajax'    => array(
      
'callback' => 'mymodule_form_ajax_callback',
      
'wrapper'  => $form['#wrapper_id'],
    ),
  );

  if(!empty(

$form_state['storage']['selected_terms'])){
    
$form['select_wrapper']['result'] = array(
      
'#type' => 'markup',
      
'#markup' => implode(', '$form_state['storage']['selected_terms'])
    );
  }

  

$form['actions']['submit'] = array(
    
'#type' => 'actions'
  
);
  
$form['actions']['submit'] = array(
    
'#type'  => 'submit',
    
// В функцию t() передавать строку только на английском
    
'#value' => t('Submit'),
    
'#ajax'  => array(
      
'callback' => 'mymodule_form_ajax_callback',
      
'wrapper'  => $form['#wrapper_id'],
      
'event'    => 'click',
    ),
  );
  return 
$form;
}

/**
 * Form validate for mymodule_form().
 */
function mymodule_form_validate($form, &$form_state) {
  
// Логика валидации.

  // Для запуска сабмит функции когда форму сабмитит селект.
  

$form_state['submitted'] = true;
}

/**
 * Form submit for mymodule_form().
 */
function mymodule_form_submit($form, &$form_state) {
  
form_state_values_clean($form_state);
  
$vals = &$form_state['values'];
  
$form_state['storage']['selected_terms'] = $vals['select_wrapper'];
  
$form_state['rebuild'] = TRUE;
}

/**
 * Реализация hook_ajax_callback()
 */
function mymodule_form_ajax_callback($form, &$form_state) {
  return 
$form;
}
?>
Аватар пользователя andem andem 19 октября 2016 в 20:11

О, супер. Работает, и выдает нужный айди. Сейчас буду разбираться как реализовано. Много новых функций. Вижу что и через валидацию нужно прогонять.
Теперь дальше буду выводить подкатегорию и зависимую ноду. Потом результат ниже формы.
mbaev, спасибо огромное за подсказку. И спасибо за свой способ реализации формы на данном этапе. Филдсет сворачивающийся мне не нужен, поэтому его убрал.

Аватар пользователя bumble bumble 19 октября 2016 в 20:37
2

@mbaev - прекрасный пример! Спасибо! Будет мне левел-ап....

Нюанс: [man=array-column]array_column()[/man] - только с 5.5 работает, для версий ниже - рекомендуют самим реализовать.

Ну, а если все поддерживается - можно трохи упростить:

<?php
// Вместо:
$tids array_column($tree'tid');
$term_names array_column($tree'name');
// и потом:
$form['select_wrapper'][0] = array(
  
'#options' => array_combine($tids$term_names),
);

// Просто:
$terms array_column($tree'name''tid');
// и в:
$form['select_wrapper'][0] = array(
  
'#options' => $terms,
);

// Или, даже сразу:
$form['select_wrapper'][0] = array(
  
'#options' => array_column($tree'name''tid'),
);
?>
Аватар пользователя mbaev mbaev 19 октября 2016 в 21:01

Спасибо, хорошая находка!
Сначала была одна такая функция, потом я добавил еще одну для $tids в другом месте, а потом они оказались рядом. Ну короче не стал оптимизировать до идеала.

Там по ссылке "своя реализация" слишком сложная. Достаточно так

<?php
$tids 
array_map(function ($item) {return $item->tid:}, $tree);
$term_names array_map(function ($item) {return $item->name;}, $tree);
?>

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

<?php
$tree 
array_map('get_object_vars'$tree);
?>
Аватар пользователя andem andem 18 октября 2016 в 20:37

Я так полагаю через функцию нужно получать значение? А какая функция должна быть?
Ребят, можете скинуть ссылку со всеми функциями для form API? А то в Form API на друпале.орг одни атрибуты.
Да, и не поймите меня не правильно. Перед тем как вопрос задать. Два дня мучаюсь над ним.

Аватар пользователя andem andem 19 октября 2016 в 20:04

Всмысле усложнять? Наоборот облегчаю. Вместо того чтобы в огромном списке всех картреджей посетитель выбирал нужный ему и узнавал цену. Я ему делаю форму, где он выберит нужный принтер, нужную модель и нужный картридж, получит цену на заправку. Все просто. ))) хотя на деле реализации этой формы, все очень слооожно)

Аватар пользователя andem andem 19 октября 2016 в 20:09

sas@drupal.org, где эти примеры? в exemples нет такой реализации. Там есть только вывод ноды. А зависимых селектов нет! А ajax мне нужен только для того чтобы он обновил информацию в последующих селектах. (Категория таксаномии>подкатегория таксаномии>Заголовок ноды>Вывод нескольких полей ноды ниже формы)

Аватар пользователя mbaev mbaev 19 октября 2016 в 20:52

andem wrote:

на данном этапе. Филдсет сворачивающийся мне не нужен, поэтому его убрал

Вангую, что добавите обратно, потому что в сабмит функции очень удобно получать:

<?php
$selected_terms 
$form_state['values']['select_wrapper'];
?>

вместо

<?php
$selected_terms
[] = $form_state['values'][1];
$selected_terms[] = $form_state['values'][2];
$selected_terms[] = $form_state['values'][3];
?>