Forms API - несколько кнопок submit.
Прислано: CynicusAE
пн, 15/03/2010 - 06:12
Доброго времени суток.
Делаю форму вида
[набор полей]
[набор полей 1]
[поле-1-1]
[поле-1-2]
[сабмит-1]
[набор полей 2]
[поле-2-1]
[поле-2-2]
[сабмит-2]
Функция построения формы (без "лишних" полей, чтобы не было избыточности информации):
function list_of_vacancies(){ // Создаем набор полей - обертку, чтобы держать информацию свернутой $form['vacancies_list'] = array ( '#title' => t('List of vacancies'), '#type' => 'fieldset', '#collapsible' => TRUE, '#collapsed' => TRUE, '#tree' => TRUE, ); $result = db_query ("SELECT * FROM {vacancy} WHERE companyid = %d", arg(1)); //Здесь начинаем строить наборы полей с содержимым и кнопками while ($item = db_fetch_object($result)){ $form['vacancies_list'][$item->fcid] = array ( '#type' => 'fieldset', '#collapsible' => FALSE, ); $form['vacancies_list'][$item->fcid]['vacancy'] = array ( '#type' => 'textfield', '#default_value' => $item->vacancyname, '#size' => 20, ); $form['vacancies_list'][$item->fcid]['salary'] = array ( '#type' => 'textfield', '#default_value' => $item->salary, '#size' => 6, ); $form['vacancies_list'][$item->fcid]['update'] = array ( '#type' => 'submit', '#value' => t('Update'), '#validate' => array ('list_of_vacancy_update_validate'), '#submit' => array ('list_of_vacancy_update_submit'), ); $form['vacancies_list'][$item->fcid]['delete'] = array ( '#type' => 'submit', '#value' => t('Delete'), '#submit' => array ('list_of_vacancy_delete_submit'), ); } // Общие для всех форм кнопки обработки. $form['vacancies_list']['update_all'] = array ( '#type' => 'submit', '#value' => t('Update all') ); $form['vacancies_list']['delete_all'] = array ( '#type' => 'submit', '#value' => t('Delete all') ); return $form; };
В итоге получается, что на каждый набор полей вызывается одна и та же функция и обрабатывает все одноименные поля сразу. Как сообщить функциям валидации и отправки, какая именно кнопка была нажата?
Или есть иной способ получить требуемый результат? Только от подобной структуры наборов полей отказываться не хочется, потому что таких групп на одной странице может быть несколько.
- CynicusAE's blog
- Для комментирования войдите или зарегистрируйтесь
http://drupal.org/node/144132#buttons
- Для комментирования войдите или зарегистрируйтесь
Не то. Более того, оное мной благополучно используется в этом же коде. Сложность в том, что количество наборов полей переменное и зависит от числа записей в базе - одно, пять, двадцать...
Выводятся они через цикл и в данном случае и '#value' => t('something') у них будут одинаковыми, и функция обработки одна и та же. Различия только в ID - ибо ['vacancies_list'][$item->fcid]['update'] (ну и удалением аналогично).
Так что вопрос остается - как сообщить функциям валидации и отправки, какая из кнопок нажата? Выбор не между update и delete, это легко решаемо, а между разными update и разными delete.
- Для комментирования войдите или зарегистрируйтесь
Решал аналогичную задачу. Надо в кнопке сохранять какой-нибудь id, а потом при сабмите проверять. Точно не помню где он будет доступен, что-то вроде $form_state['submit'].
На орге об этом есть информация, поищите. Если не найдете, могу примерно после 15:00 посмотреть свой код.
- Для комментирования войдите или зарегистрируйтесь
проще было бы одну кнопку с условиями на селектах или радиобаттонах.
попробуй принтануть form_state
- Для комментирования войдите или зарегистрируйтесь
hook_forms()? Не?
- Для комментирования войдите или зарегистрируйтесь
hook_forms()? Не?
Да не, он же вроде одну форму генерирует, а не несколько форм с одним набором обработчиков.
Там не нужны никакие дополнительные поля, селекты и баттоны, надо id набора полей сохранять в массиве-описании соответствующей кнопки, он будет передан в форм-стейт, надо только вспомнить, куда именно :)
- Для комментирования войдите или зарегистрируйтесь
Во, нашел.
form_state['clicked_button']
A full copy of the button element that was clicked to submit the form. This is more reliable than the old $form_values['op'] name, and also carries any additional information that was placed in the button element's form definition.
Это с той же страницы, что Nikit в начале привел. По-моему так оно и делается. После обеда проверю.
- Для комментирования войдите или зарегистрируйтесь
form_state['clicked_button']
Тогда надо не забыть каждой кнопки свой ID назначать, да так чтоб потом различить
- Для комментирования войдите или зарегистрируйтесь
Ага, я так и написал: надо id набора полей сохранять в массиве-описании соответствующей кнопки. $item->fcid из приведенного кода, вероятно, подойдет.
Но, кстати, у использования hook_forms() и генерации множества одинаковых форм есть свои плюсы. Например, легко потом повесить аякс на сабмит каждой формы. Ну и движку не нужно будет тащить в form_state значения всех групп полей при сабмите только одной группы.
- Для комментирования войдите или зарегистрируйтесь
Да вот мне тоже вариант с hook_forms() больше нравится, гибче
- Для комментирования войдите или зарегистрируйтесь
Обычно это делается так:
<?php $form['buttons'] = array();
$form['buttons']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
'#weight' => 5,
'#validate' => array('validate_func_1'),
'#submit' => array('submit_func_1'),
);
$form['buttons']['delete'] = array(
'#type' => 'submit',
'#value' => t('Delete'),
'#weight' => 15,
'#validate' => array('validate_func_2'),
'#submit' => array('submit_func_2'),
);
?>Ну можно конечно навесить ID и обойтись 2-мя функциями, но имхо лучше разделять.
- Для комментирования войдите или зарегистрируйтесь
Тут вроде речь про случаи с неизвестным/переменным числом кнопок.
- Для комментирования войдите или зарегистрируйтесь
Спасибо ответившим.
Пока реализовал с помощью '#name' -> $item->fcid,в свойствах кнопки и проверки $form_state['clicked_button']['#name']в функциях.
На hook_forms() посмотрю. Похоже, это действительно будет более правильным и удобным решением.
- Для комментирования войдите или зарегистрируйтесь
Кликнутая кнопка в *_submit доступна через:
$sta['clicked_button']
<?php
function *_submit($frm, &$sta) {
drupal_set_message($sta['clicked_button']['#value']);
}
?>- Для комментирования войдите или зарегистрируйтесь


Комментарии