[решено] не корректная работа форм, выведеных в цикле

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

Аватар пользователя kaoru.nspb kaoru.nspb 3 июля 2010 в 14:58

задача - вывести выборку из БД, добавив к каждой строчке выборки кнопку удаления.

делаю следующее:
каждая строчка выборки заключается в тег span, кнопка удаления строчки выборки из БД реализуется как форма.
вот цикл в котором генерируется хтмл с формами кнопок удаления:

while ($db_output = db_fetch_object($result)) {
            $html_output .= '<span class="item'.$db_output->itemid.'">'.$db_output->itembody.''.drupal_get_form("mymodule_del_item_form", $db_output->itemid).'</span>';
}

вот конструктор формы кнопки удаления:

function mymodule_del_item_form($form_state, $itemid = -1) {
    $form['item_id'] = array(
        '#type' => 'value',
        '#value' => $itemid,
    );
    $form['submit'] = array(
        '#type' => 'submit',
        '#value' => 'удалить',
    );
    return $form;
}

результат:
хтмл генерируется верно (классы тега span нумеруются верно, экземплярам формы присваиваются уникальные номера и т.д.)

проблемма:
при нажатии на любою кнопку удаления форме передается один и тот же $itemid, значение которого всегда равно itemid первой строчки выборки. то есть при попытке удалить любую (не обязательно первую из выборки)строчку из БД, удаляется всегда та, которая была отсортирована первой при выборке.

иными словами на примере:

выборка=
строчка1: itemid=1, itembody='body1'
строчка2: itemid=2, itembody='body2'
строчка3: itemid=3, itembody='body3'

хтмл=

<span class="item1">body1<form ... id="mymodule-del-item-form"> ... </form></span>
<span class="item2">body2<form ... id="mymodule-del-item-form-1"> ... </form></span>
<span class="item3">body3<form ... id="mymodule-del-item-form-2"> ... </form></span>

что происходит=
нажатие на кнопку из <form ... id="mymodule-del-item-form"> ... </form> ведет к удалению строчки1
нажатие на кнопку из <form ... id="mymodule-del-item-form-1"> ... </form> ведет к удалению строчки1
нажатие на кнопку из <form ... id="mymodule-del-item-form-2"> ... </form> ведет к удалению строчки1

вопрос:
что нужно сделать, что бы работало следующим образом:
нажатие на кнопку из <form ... id="mymodule-del-item-form"> ... </form> вело к удалению строчки1
нажатие на кнопку из <form ... id="mymodule-del-item-form-1"> ... </form> вело к удалению строчки2
нажатие на кнопку из <form ... id="mymodule-del-item-form-2"> ... </form> вело к удалению строчки3
?

Комментарии

Аватар пользователя Ch Ch 3 июля 2010 в 19:25

Попробуй так:

function mymodule_del_item_form($form_state, $itemid = -1) {
    $form['item_id_'.$itemid] = array(
        '#type' => 'value',
        '#value' => $itemid,
    );
    $form['submit_'.$itemid] = array(
        '#type' => 'submit',
        '#value' => 'удалить',
    );
    return $form;
}
Аватар пользователя andypost@drupal.org andypost@drupal.org 3 июля 2010 в 20:19

Все формы имеют идентичное название... вот и подхватывается первая
input type="hidden" name="form_id"

Для правильной реализации такого подхода нужно использовать hook_forms

Вот работающий пример:
<?php
function test_menu() {
$items['test'] = array(
'title' => 'Test',
'page callback' => '_test_menu',
'access arguments' => array('access content'),
);
return $items;
}

function _test_menu() {
$output = '';
for ($i=1; $i < 4; $i++) {
$output .= drupal_get_form('test_foo' . $i, $i);
}
return $output;
}

function test_forms($form_id, $args) {
if (strpos($form_id, 'test_foo') === 0) {
return array($form_id => array('callback' => 'test_foo'));
}
}

function test_foo(&$form_state, $id) {
$form['#item'] = $id;
$form['del'] = array(
'#type' => 'submit',
'#value' => 'Del ' . $id,
);
$form['#submit'] = array('test_foo_submit');
return $form;
}

function test_foo_submit($form, $form_state) {
drupal_set_message($form['#item']);
}
?>

Аватар пользователя kaoru.nspb kaoru.nspb 4 июля 2010 в 1:37

Ch, попробовал, не работает..

andypost, спасибо, добавил хук формс, все работает Smile
только не понял, зачем принудительно в конструкторе формы свойство "submit" выставлять? ведь, например, вроде бы для формы mymodule_del_item_form функция mymodule_del_item_form_submit должна по умолчанию выполняться при отправке формы.

Аватар пользователя kaoru.nspb kaoru.nspb 5 июля 2010 в 0:22

"<a href="mailto:andypost@drupal.org">andypost@drupal.org</a>" wrote:
Может и не нужно, не пробовал...

нет. как раз нужно, без этого не работало.
и в подтверждение - сегодня читал Дж.Вандюка, он пишет, что если не существует конструктора формы test_foo1(), то будет вызван перехватчик hook_forms() и тогда друпал вызовет test_foo() в качестве конструктора. Однако, для проверки и отправки формы друпал будет пытаться вызывать test_foo1_validate() и test_foo1_submit() соответственно.
т.о. свойства submit и validate нужно обязательно выставлять на соответствующие функции. или, как я подозреваю, указывать это в hook_forms().

Аватар пользователя andypost@drupal.org andypost@drupal.org 5 июля 2010 в 3:11

Спасибо за разъяснения, просто привык писать именно таки образом. Видимо когда-то наступил на эти грабли и отложилось как нужно писать Smile

EDIT: проверил, в ядре используется именно такой подход http://api.drupal.ru/api/function/trigger_assign_form/6