phpformsdrupal

drupal multiple node forms on one page


I have a view that displays several nodes. I want to place node form below each displayed node. Both node_add and drupal_get_form directly in template.php works fine, but I get forms with same form ID of NODETYPE_node_form and validation and submitting does not work as expected.

If you had to put several node forms on one page, what would be your general approach?

Progress so far...

in template.php while preprocessing node $author_profile and $content is set before.

$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);

in mymodule module

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';
    }
}

Questions

My take on summarizing unclear questions...

  1. Is this good general approach for displaying multiple node forms on same page?
  2. Is it OK to copy/paste code from content modules content_form_alter function in function mymodule_form_alter? Will it not brake things if content module is updated?
  3. Should i set $form['#id']? Without it all forms has same HTML form ID of node_form, with it ID is unique, like review_node_form_254. Thing is that there is no difference of how form is submitted. Setting $form['#validate'][0] does not seem to influence things too. Maybe I should set $form[button]['#submit'][0] to something else? Now its node_form_submit.
  4. Why validation does not work even with unique form id and form validate function? If i submit last form without required field all previous forms gets particular fields red. should I make my own validation function? what level - form or field? Any tips on where to start?

Solution

  • I really did not dig to the bottom of it, but it seems to me that you pretty much did all the relevant digging by yourself.

    From what I understand by inspecting the code only, you are right in thinking that content_form_alter() is the show-stopper.

    Maybe this is a naïve suggestion, but what about writing your own implementation of hook_form_alter() starting from the content_form_alter() code but changing the conditions that make the alteration to occur? I am thinking to something along these lines:

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

    I did not actually test the code above, but I hope it is self-explenatory: you actually trigger the changes for a give customised type of content if MYCCKTYPE_node_form is a substring of the actual form_id (es: MYCCKTYPE_node_form_234).

    Hope this helps at least a bit... Good luck! :)

    EDIT: TWO MORE THINGS

    1. It just occurred to me that since your custom implementation of hook_form_alter() will live aside the CCK one, you would like to add a check to avoid the form to be modified twice something like:

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

    2. The other way you might try to implement this by not using CCK but implementing you custom type programmatically (this might even be an advantage if you plan to use your module on various different sites).