tags:

views:

1386

answers:

2

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?
A: 

You need to implement hook_forms() to map different ids to the same builder function.

The NODETYPE_node_form ids you mention are already an example of this mechanism, as they are all mapped to the same builder function (node_form()) within the node modules node_forms() implementation.

You can find links to more examples in the 'Parameters' explanation off the drupal_get_form() function.

Henrik Opel
Problem is that there are multiple forms on page so form id must be unique, like NODETYPE_node_form_UNIQUENUMBER. with node hook_forms() i can add callback 'node_form' to NODETYPE_node_form_UNIQUENUMBER, but in return i get generic node form, not my NODETYPE node form.
henrijs
i already tried solutions from here http://www.computerminds.co.uk/drupal-6-multiple-instances-same-form-one-page and here http://drupal.org/node/336870 but with little luck
henrijs
@henrijs: The approach you describe in your first comment should work - how are you calling `drupal_get_form()`? (You need to pass the node object as the second argument after your custom form id)
Henrik Opel
@henrijs: Maybe you can edit your question and add the code for the form injection you have so far?
Henrik Opel
A: 

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).

mac
Yes, now i get correct MYCCKTYPE node form. Very cool indeed, but form ID is still same for all forms - "node_form". Well actually, themer module tells me that form['#id'] is "node_form" and form['form_id']['#value'] is MYCCKTYPE_node_form_234 how would i get form['#id'] and therefore actual html form id to be MYCCKTYPE_node_form_234 + unbroken javascript in "split summary at cursor" + proper validation and submit. hmmm...
henrijs
All right, i think i can brutally add $form['#id'] = $form_id; to my modulename_form_alter and i get nice $form['#id'] = 'MYCCKTYPE_node_form_234' as well as html form id is now ok, form submits good but javascript in "split summary at cursor" is still wrong (shows button for first form only, checkboxes for other forms as if button there is clicked) and validation is not good also - it works but marks red fields for forms after one being submited
henrijs
Happy to see the hint was useful.Can't really say for sure, but the red contours in validation are usually set by http://api.drupal.org/api/function/form_set_error/6 which is normally called from within the validation function and has no $form or $form_state amongst its parameters. It might therefore be that either those params are wrong in the validation, either a bug in the core.You could try to assign validation by explicitly indicating a validation function on a per-form basis via `$form['#validate']`, or even getting down to a per-element validation and see if that fixes it...
mac
Unless you pastebin your code so that I (or anybody else) can try to debug it, I don't think I can't help much further. The only general tip I can give you is to look in some similar code and try to see by comparison where the bug you are experiencing lies... Although it's not CCK but standard forms, ubercart has a very similar way of handling multiple forms of the same kind on a page (i.e. by appending a number to the form_id) in its uc_product.module. Look for the **uc_product_add_to_cart_form** related code.
mac
Weird... my last comment was a response to a comment of yours that now disappeared... :-/
mac
i deleted my comment, sorry. i am working all the time on this and 2 other ways to get what i want, one way code is up there in question, i will definitely come back and paste some more code soon.
henrijs