I have a custom field formatter on an Event node that displays data from a multifield in a simple HTML table (the multifield has a user entity reference field and a text field that contains a number of RSVPs for the event). In order to allow the user to enter a number for the text field, I'm displaying a ctools modal window containing a form with a text field. When the form is submitted, I want to do two things:
- Update the multifield in the node with the new data, and
- Update the table with the name as a link to remove the data from the node.
I've done something similar before where I update a node edit form from a modal using an ajax link, and I also have this working using an ajaxified link, but I'm having problems getting this to work from a form submit function in a modal window.
Here's the relevant code:
function cfd_duty_menu() {
$items = array();
$items['rsvp/%ctools_js/%/%'] = array(
'page callback' => 'cfd_duty_rsvp_page',
'page arguments' => array(1, 2, 3),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Page callback for ctools modal window.
*/
function cfd_duty_rsvp_page($ajax, $uid, $nid) {
if ($ajax) {
//Load the modal library and add the modal javascript.
ctools_include('ajax');
ctools_include('modal');
$form_state = array(
'ajax' => TRUE,
'title' => t('RSVP Form'),
'uid' => $uid,
'nid' => $nid,
);
// Add custom settings for form size.
drupal_add_js(array(
'rsvp-modal-style' => array(
'modalSize' => array(
'type' => 'fixed',
'width' => 500,
'height' => 500,
),
),
), 'setting');
// Use ctools to generate ajax instructions for the browser to create
// a form in a modal popup.
$output = ctools_modal_form_wrapper('cfd_duty_rsvp_form', $form_state);
// If the form has been submitted, there may be additional instructions
// such as dismissing the modal popup.
if (!empty($form_state['ajax_commands'])) {
$output = $form_state['ajax_commands'];
}
// Return the ajax instructions to the browser via ajax_render().
print ajax_render($output);
drupal_exit();
}
else {
return drupal_get_form('cfd_duty_rsvp_form', $uid, $nid);
}
}
/**
* Form function for RSVP modal form.
*
* @param $form
* @param $form_state
* @param $uid
* @param $nid
*
* @return array
*/
function cfd_duty_rsvp_form($form, $form_state) {
$form = array();
$user = entity_load('user', array($form_state['uid']));
$user_name = $user[$form_state['uid']]->name;
$form['name'] = array(
'#type' => 'markup',
'#markup' => '<div>' . $user_name . '</div>',
);
$form['event_nid'] = array(
'#type' => 'value',
'#value' => $form_state['nid'],
);
$form['user_name'] = array(
'#type' => 'value',
'#value' => $user_name,
);
$form['rsvp_num'] = array(
'#type' => 'textfield',
'#title' => t('How many?'),
'#size' => 2,
'#maxlength' => 2,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
return $form;
}
/**
* Drupal form submit handler for RSVP form.
*/
function cfd_duty_rsvp_form_submit(&$form, &$form_state) {
$event_node = entity_load('node', array($form_state['nid']));
$event_node = $event_node[$form_state['nid']];
$uid = $form_state['uid'];
$div_id = 'event-' . $uid;
$rsvp_num = $form_state['values']['rsvp_num'];
// First, need to check to make sure that the RSVP limit for this event has not been exceeded.
$rsvp_limit = (int)$event_node->field_max_rsvp[LANGUAGE_NONE][0]['value'];
if (count($event_node->field_rsvp_slots[LANGUAGE_NONE]) < $rsvp_limit) {
// Add to field_volunteer.
// Code to update the node goes here.
// Build the remove link.
$output = '<tr id="' . $div_id . '"><td>' . l(t($form_state['values']['user_name']), 'cfd_duty/signup/event/remove/' . $uid . '/' . $form_state['nid'] . '/nojs/', array(
'attributes' => array(
'class' => array('use-ajax'),
'title' => t('Remove signup')
}
)) . '</td><td>' . $form_state['values']['rsvp_num'] . '</td></tr>';
}
//$form_state['ajax_commands'] = array();
// Tell the browser to close the modal.
$form_state['ajax_commands'][] = ctools_modal_command_dismiss();
// Replace the div on the page.
$form_state['ajax_commands'][] = ajax_command_replace($div_id, $output);
}
And here's the HTML table markup (pretty simple).
<table class="sticky-enabled">
<caption>RSVPs</caption>
<thead>
<tr>
<th>Name</th>
<th>Count</th>
</tr>
</thead>
<tbody>
<tr id="event-13" class="odd">
<td><a href="/rsvp/nojs/13/35/nojs/" class="use-ajax ajax-processed" title="Sign up">Sign up</a></td>
<td></td>
</tr>
</tbody>
</table>
When the submit function runs, the node is updated properly, but the content isn't changed. I've tried addig the `#` to the $div_id value, but it doesn't make a difference. If I add
$form_state['ajax_commands'][] = ctools_ajax_command_reload();
it reloads the page, but it's sort of clunky.
What do I need to do to get the markup replaced without having to reload the page?
Thanks.
Comments
Comment #1
MustangGB CreditAttribution: MustangGB commented