Multiple forms on one page

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
legion80's picture

Hello,

I have been struggling with a forms issue that I thought maybe someone could help answer for me.

Basically I am trying to have several drupal forms laid out in one page, with one "Save" button, which will save all of the forms on the page at once. Each form is already assumed to edit an existing node, so I do not need to worry about the case where the user is creating a new set of nodes from the forms on the page.

More specifically, one of the forms comes from the content_profile module, and the page is where the user is editing his profile. The content_profile module permits the user to create only one node of the "profile" content type. There is a set of information that I would like to expose through the profile to the user, but that set needs to be stored in a content type that allows users to create more than one node of that type. I should mention that there are fields that are only needed for the profile, and those fields are in the profile content type.

So for example, I have a "person" content type that has a field for first name and last name. This content type will be used for more than just users of the website. The "profile" content type has two fields: a URL to the user's blog, and a node reference which refers to the person node that corresponds to the user.

Let's assume that when a user signs up to the website, a profile and a person node are created and attributed to that user. (I managed to figure that part out.)

When a user edits their profile (/user/%uid/profile/profile, for those familiar with content_profile), I would like the node edit form for "profile" as well as his "person" node (determined by the node reference CCK field) to show up in the profile edit form. I only want one "Save" button. When they save their changes, both nodes are saved.

Is there some easy way to do this? Currently the form is just saving the fields relevant to the "profile" node, which is to be expected, since all of the $_POST information refers to the profile node's ID. I wanted to see if I could programmatically save the user's "person" node, but didn't know how to accurately map the data from $_POST (which gets transferred to $form_state) to the node returned by node_load(). I also tried to fake a submission and run it through the normal node submission handlers, but then the code doesn't validate because of bad form_build_id's and tokens and other esoterica that I have yet to understand.

I know that one could propose just merging the fields into the profile node, and keep the person node for those other nodes that the user creates, but there are other reasons I cannot do this. I also think that going forward it's not necessarily a sustainable way to grow the site, because if the "person" content type changes, someone has to remember to also change the "profile" content type to preserve the schema.

Much thanks,
Jon

Comments

Still, the reason for two?

matt.lutze's picture

Can you please offer a bit more information?

Is this a production site you're making upgrades to, or a new site altogether? I may be slow, or not seeing something plainly obvious, but I'm not certain why one would need "the person node for those other nodes that the user creates." I presume, that some "People" nodes refer to actual users on the site (and therefore you maintain a link to a "profile" node) while others are not users of the site. In both cases, you associate other created nodes with "People." Is this close?

If so, what other use cases do you have for the "People" node? Maintaining a node for what a lighter solution might suffice seems unnecessary, unless there's other reasons to have both content types.

This is a new site I'm

legion80's picture

This is a new site I'm working on, not an upgrade to an existing web site.

You are correct in your assumptions about how some "person" nodes are actual users, and other "person" nodes are not. You mentioned maintaining links from a "person" to a "profile"; I actually have the relationship the other way around at this point, where a "profile" links to a "person".

I don't have other use cases for the "person" node. This use case comes up multiple times though. Basically the schema I designed has a "person" as a base class, if you will, and then different aspects, or occupations, of a person can be attached to the person. Each aspect is its own content type, and contains its own unique fields. The profile and person problem I have here is an example of that. A person, for example, might be a business owner. I have a content type "business owner" with fields relevant to that, and an additional node reference field to the person node.

I have 4 different aspects that could be attached to a person in any combination. You could argue that I just merge all of them into the "person" and the "profile" node types, but that would make the schema really long and unmanageable. And again, if I had to update the field for an aspect, I'd have to remember to apply it to both cases. I thought that having a schema that kept the aspects separate would be easier to maintain, and the display logic easier. My only issue now is I can't show multiple forms on one page.

Have you seen this blog post

krlucas's picture

Have you seen this blog post from Advomatic:
http://www.advomatic.com/blogs/jonathan-delaigle/multiple-nodes-single-n...

This happens to be for node creation but it might be helpful.

Seems like you could create a custom form definition that retrieves the node edit form definitions for each of your nodes using drupal_retrieve_form and then merges them together, instead of duplicating the same CCK fields on the "profile node" that are necessary for "person node", as this tutorial would suggest.

An interesting puzzle...look forward to hearing how you work/worked through it.

Thanks for the link to

Bilalx's picture

Thanks for the link to advomatic. It would be nice indeed to know if someone found a solution to the problem at hand.

a related question

monti's picture

for myself and for others, who will come across this discussion in the future -

does anybody know how to permanently link between a user-page and the user's conten_profile's node?

I would like registration (create), edit and view of either [user|node] to handle both parts.

Cheers !

To make my question clearer

monti's picture

To make my question clearer -

I think it's pretty confusing for the standard user to check (& edit) their profile settings at so many different paths -

I'd like to save them the headache and have everything - "user-page" as well as content_profile - on the same page or at least linked to each other through tab-menu.

additionally (this part confuses also me...) -
http://example.com/user/uid/profile/profile is the same as the corresponding
http://example.com/node/nid/edit

http://example.com/user/uid/profile, however, embeds data from
http://example.com/node/nid

I find the above pretty messy (don't you?) and would very much like to put some order in it.
If anybody can share an insight or idea, it'd greatly help the rest of us.

looks like I am responding to myself

monti's picture

so, at least, others would benefit -

I created links from one to the other and vice verse and additionally I created a simple block to let the user know what's what -

here is the code:

<?php
global $user;
$myuid$user->uid;
$profilenode= content_profile_load(profile, $myuid);
$profilenid= $profilenode->nid;
?>


<ul><li>
<?php echo l(t('My account'),'user/'.$myuid); ?>
</li><li>
<?php echo l(t('My public profile'),'node/'.$profilenid); ?>
</li><li>
<?php echo l(t('Public profile settings'),'node/'.$profilenid.'/edit'); ?>
</li><li>
<?php echo l(t('Logout'),'logout'); ?>
</li></ul>

a small change to make sure the profile exists

monti's picture

before sending the the user to nowhere -

<?php
global $user;
$myuid$user->uid;
$profilenode= content_profile_load(profile, $myuid);
$profilenid= $profilenode->nid;
?>


<ul><li>
<?php echo l(t('My account'),'user/'.$myuid); ?>
</li><li>
<?php if (!empty($profilenid)) {
         echo
l(t('My profile'),'node/'.$profilenid);
         echo
'</li><li>'.l(t('Profile settings'),'node/'.$profilenid.'/edit');
      } else {
         echo
l(t('Profile settings'),'node/add/profile');
      }
?>

</li><li>
<?php echo l(t('Logout'),'logout'); ?>
</li></ul>

Hasn't anyone cracked this nut yet?

DanGarthwaite's picture

We've needed this for years now with a user base of 13k and multiple content_profile content types...

It's a nightmare to code with all the different user permissions as a user is signing up.
anonymous -> logintobaggin pending -> friend

Different roles can't 'Back' to previous pages, they get access denied.

The user's home page becomes a mess of forms.

What would be really sweet ( say two content_profile types 'address' and 'about_me' per user :

my_unnamed_function_hook() {
  $forms[] = drupal_get_form('user', $uid);
  $forms[] = drupal_get_form('address', $uid);
  $forms[] = drupal_get_form('about_me', $uid);

  foreach( $forms as $f )
    $content .= drupal_render($f)
  return $content;
}


my_form_submit(&$form) {
  // this is just called three times
  # normal form handling stuff
}

of course on any error, all three forms would have to be redisplayed. sigh

Been a year and a half and

DanGarthwaite's picture

Been a year and a half and here I am... rewriting that mess of code, again.

D7 solves most of the headaches with entities but still not easy.

Multiple Forms module?

David_Rothstein's picture

For Drupal 7, you might want to take a look at the Multiple Forms module (http://drupal.org/project/multiform) which seems like it would help with this exact use case.

awsome!

cbluet's picture

thanks for link. exactly what i was looking for.

~charleston blue

Boston

Group categories

More Specifically

Group events

Add to calendar

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds:

Hot content this week