For a couple different sites now, I've done this using a ctools modal, and here's the basic outline of how I've implemented it (very simply):
Create a custom page callback in your module's hook_menu() that displays a basic node form for the node you want to reference (for a 'student' node, just have a name field and maybe a graduating year field). On that form, in your submit callback, save the node using node_save(), and store the node ID (which should be at $node->nid after you pass a new node object to node_save()) in the form's $form_state['storage']['student_id']
.
Alter the master/Class node form using hook_form_alter(). You need to do a few things here:
First, you need to add in the ctools modal javascript and
functionality so ctools knows what to do with your special link:
// Add in ctools modal js and functionality.
ctools_include('modal');
ctools_modal_add_js();
Second, you need to add a link to the page callback you created in step 1 in hook menu, and with that link, add the class 'ctools-use-modal'. So, for example:
// Add link to custom student form callback with ctools modal.
$form['add_student_link'] = array(
'#markup' => l(t('Add Student'), 'mymodule/add-student', array('attributes' => array('class' => array('ctools-use-modal')))
);
- In your custom page callback, you need to do a few things to make it work with or without JavaScript, and with ctools' form functions.
Here's an example callback:
<?php
function mymodule_student_form_callback($js = FALSE) {
// Make sure $js (set by ctools) is TRUE/loaded.
if ($js) {
// Add in ctools modal form stuff.
ctools_include('modal');
ctools_include('ajax');
$form_state = array(
'ajax' => TRUE,
'title' => t('Create a Student'),
);
$output = ctools_modal_form_wrapper('mymodule_create_student_form', $form_state);
}
else {
return 'Javascript must be enabled for this feature to work.';
// Or, if we wanted to load the form normally...
// return drupal_get_form('mymodule_create_student_form');
}
// If the form is executed, dismiss the form and reload the page.
if ($form_state['executed']) {
$commands = array();
// Close the frame.
$commands[] = ctools_modal_command_dismiss();
// Use one of the ajax framework commands to place the returned
// student node nid into the proper form value, placholder div, etc.
// See: http://api.drupal.org/api/drupal/includes%21ajax.inc/group/ajax_commands/7
$commands[] = ajax_command_append('#student-id-placeholder', $form_state['storage']['student_id']);
$output = $commands;
}
// Render the output.
print ajax_render($output);
exit();
}
?>
In mymodule_create_student_form($form, $form_state)
, build your form like you normally would, and then in the mymodule_create_student_form_submit(form, &$form_state)
(submit) function, set the value of the NID of the newly created student node in $form_state['storage']['student_id']
. This is how you'll get ctools/AJAX to pass back the new nid to your original Class form.
In my situation, I was using the modal to spit back some markup to the original page, so I passed the markup into a placeholder div using ajax_command_append()
, then I had some jQuery on the original page monitoring the placeholder div, and when it found content in it, it would move the HTML into the proper place elsewhere on the node form. In your case, you'll need to populate a single or multi-value node reference field, which may be a little more complex. I haven't needed to do that yet... so I don't have more advice to offer for that part of the equation.