Drupal многоузловой формы на одной странице - PullRequest
3 голосов
/ 11 ноября 2009

У меня есть представление, которое отображает несколько узлов. Я хочу разместить форму узла ниже каждого отображаемого узла. И node_add, и drupal_get_form напрямую в template.php работают нормально, но я получаю формы с одинаковым идентификатором формы NODETYPE_node_form, а проверка и отправка не работают должным образом.

Если бы вам пришлось разместить несколько форм узлов на одной странице, каков был бы ваш общий подход?

Прогресс на данный момент ...

в template.php во время предварительной обработки узла $ author_profile и $ content установлены ранее.

$unique = $vars['node']->nid;

$node = new StdClass();
$node->uid = $vars['user']->uid;
$node->name = $vars['user']->name;
$node->type = 'review';
$node->language = '';
$node->title = t('Review of ') . $vars['node']->realname . t(' by ') . $vars['user']->realname . t(' on ') . $content->title;
$node->field_review_to_A[0]['nid'] = $nodeA->nid;
$node->field_review_to_B[0]['nid'] = $vars['node']->nid;
$node->field_review_to_profile[0]['nid'] = $author_profile->nid;

if(!function_exists("node_object_prepare")) {
    include_once(drupal_get_path('module', 'node') . '/node.pages.inc');
}

//$vars['A_review_form'] = drupal_get_form('review_node_form', $node);
$vars['A_review_form'] = mymodule_view($node, $unique);

в модуле mymodule

function mymodule_view($node, $unique) {
    if(!function_exists("node_object_prepare")) {
        include_once(drupal_get_path('module', 'node') . '/node.pages.inc');
    }
    $output = drupal_get_form('review_node_form_' . $unique, $node);
    return $output;
}

function mymodule_forms($form_id, $args) {
    $forms = array();
    if (strpos($form_id, "review_node_form_") === 0) {
        $forms[$form_id] = array('callback' => 'node_form');
    }
    return $forms;
}


function mymodule_form_alter(&$form, $form_state, $form_id) {
    if (isset($form['type']) && isset($form['#node']) && $form_id != $form['type']['#value'] .'_node_form' && $form['type']['#value'] == 'review') {
        $type = content_types($form['#node']->type);
        if (!empty($type['fields'])) {
            module_load_include('inc', 'content', 'includes/content.node_form');
            $form = array_merge($form, content_form($form, $form_state));
        }
        $form['#pre_render'][] = 'content_alter_extra_weights';
        $form['#content_extra_fields'] = $type['extra'];

        //$form['#id'] = $form_id;
        //$form['#validate'][0] = $form_id . '_validate';

        $form['title']['#type'] = 'value';
        $form['field_review_to_A']['#type'] = 'value';
        $form['field_review_to_B']['#type'] = 'value';
        $form['field_review_to_profile']['#type'] = 'value';
    }
}

Вопросы

Мой взгляд на обобщение неясных вопросов ...

  1. Это хороший общий подход для отображения нескольких форм узлов на одной странице?
  2. Можно ли копировать / вставлять код из content модулей content_form_alter функция в функции mymodule_form_alter? Не тормозит ли это, если content модуль обновлен?
  3. Должен ли я установить $form['#id']? Без него все формы имеют одинаковый идентификатор формы HTML node_form, с этим идентификатор уникален, как review_node_form_254. Дело в том, что нет никакой разницы в том, как форма отправляется. Установка $form['#validate'][0], похоже, тоже не влияет на вещи. Может быть, я должен установить $form[button]['#submit'][0] на что-то еще? Теперь его node_form_submit.
  4. Почему проверка не работает даже с уникальным идентификатором формы и функцией проверки формы? Если я отправляю последнюю форму без обязательного поля, все предыдущие формы получают определенные поля красного цвета. я должен сделать свою собственную функцию проверки? какой уровень - форма или поле? Любые советы о том, с чего начать?

Ответы [ 3 ]

2 голосов
/ 12 ноября 2009

Вам необходимо реализовать hook_forms(), чтобы отобразить разные идентификаторы в одну и ту же функцию компоновщика.

Идентификаторы NODETYPE_node_form, которые вы упоминаете, уже являются примером этого механизма, поскольку все они отображаются на одну и ту же функцию компоновщика (node_form()) внутри узловых модулей node_forms() реализация.

Вы можете найти ссылки на другие примеры в объяснении «Параметры» для функции drupal_get_form().

1 голос
/ 11 июля 2011

Это было исключительно полезно для меня.

Документация по всем API-интерфейсам Drupal так отсутствует - я рвал на себе волосы. Для меня решающее значение имеет то, что я не думаю, что оно где-либо еще в сети:

CCK добавляет свои поля в форму через hook_form_alter (). Но это делается на основе form_id. Поэтому, если идентификатор формы отличается (потому что вы хотите, чтобы на одной странице было несколько), вам нужно повторить немного кода CCK, чтобы добавить поля в форму независимо от того.

Это то, что это делает блестяще.

0 голосов
/ 13 ноября 2009

Я действительно не докопался до сути, но мне кажется, что вы в значительной степени проделали все соответствующие раскопки самостоятельно.

Из того, что я понимаю, изучая только код, вы правы, считая, что content_form_alter () является ограничителем показа.

Может быть, это наивное предложение, но как насчет написания вашей собственной реализации hook_form_alter () , начиная с кода content_form_alter () , но изменяя условия, которые вызывают изменение? ? Я думаю о чем-то вроде этого:

function modulename_form_alter(&$form, $form_state, $form_id) {
  if (isset($form['type']) && isset($form['#node']) && 
  stripos($form_id, $form['type']['#value'] .'_node_form')) {
    ...
  }
}

Я не на самом деле тестировал приведенный выше код, но я надеюсь, что он самообъясним: вы фактически инициируете изменения для заданного настраиваемого типа контента, если MYCCKTYPE_node_form является подстрокой фактического form_id : MYCCKTYPE_node_form_234).

Надеюсь, это поможет хоть немного ... Удачи! :)

РЕДАКТИРОВАТЬ: ДВА БОЛЬШЕ

  1. Мне просто пришло в голову, что, поскольку ваша пользовательская реализация hook_form_alter () будет жить в стороне от CCK, вы хотели бы добавить проверку, чтобы избежать изменения формы дважды, например:

    && $form_id != $form['type']['#value'] .'_node_form'

  2. Иначе вы можете попытаться реализовать это, не используя CCK, а внедрив свой пользовательский тип программно (это может даже быть преимуществом, если вы планируете использовать свой модуль на различных сайтах).

...