Posted by JordanMagnuson on March 15, 2012 at 1:21am
10 followers
| Project: | Chaos tool suite (ctools) |
| Version: | 7.x-1.x-dev |
| Component: | Modal |
| Category: | bug report |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | reviewed & tested by the community |
Issue Summary
I have a regular (non-modal) drupal form... when the user hits "submit," I want to open a modal dialog...
I've set up a ctools modal callback, and it's working correctly:
<?php
$items['download-manager/%ctools_js/download/%'] = array(
'title' => 'Go to the download form for a particular node.',
'page callback' => 'download_manager_wizard',
'page arguments' => array(1, 3), // %ctools_js, %nid
'access callback' => TRUE,
'type' => MENU_CALLBACK,
'file' => 'download_manager_wizard.inc',
);
?>The modal opens fine using:
<?php
ctools_modal_text_button(t('Download'), 'download-manager/nojs/download/' . $nid, t('Download this asset'), 'download-button');
?>But from within my form this does not work:
<?php
$form['#action'] = url('download-manager/ajax/download/122');
?>That just gets me an ajax waterfall dump... what should I be doing to open the modal from form submit?
Comments
#1
I've also tried adding the "ctools-use-modal" class to my form's submit button, but no luck. A modal begins to popup, but instant error messages:
<?php$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Download'),
'#attributes' => array(
'class' => array('ctools-use-modal'),
),
);
?>
#2
Hmm. That really ought to work. Perhaps there's a bug.
Have you tried with CTools -dev?
#3
Thanks a lot for the reply Merlin! I really appreciate your willingness to help.
Okay, just tried the dev, and still having the same issue. If you want to scan my code, here are github links to download_manager.module and download_manager_wizard.inc.
Or for limited reference, here's my complete form callback:
<?php
function download_manager_download_form($form, &$form_state, $nid) {
$node = node_load($nid);
// ---------------------------------------------------------------------------
// Get license options
$licenses = array();
foreach ($node->field_license['und'] as $l) {
$licenses[] = $l['value'];
}
// Define options array
$license_options = array();
// Personal use
if (in_array(PERSONAL_USE_LICENSE_ID, $licenses)) {
$personal_use_price = $node->field_personal_use_price['und']['0']['value'];
if ($personal_use_price == 0) {
$personal_use_price_text = '<span>FREE</span>';
}
else {
$personal_use_price_text = '$' . $personal_use_price;
}
$license_options[PERSONAL_USE_LICENSE_ID] = $personal_use_price_text . ' | Personal Use Unlimited';
}
// Commmercial use
if (in_array(COMMERCIAL_USE_LICENSE_ID, $licenses)) {
$commercial_use_price = $node->field_commercial_use_price['und']['0']['value'];
if ($commercial_use_price == 0) {
$commercial_use_price_text = '<span>FREE</span>';
}
else {
$commercial_use_price_text = '$' . $commercial_use_price;
}
$license_options[COMMERCIAL_USE_LICENSE_ID] = $commercial_use_price_text . ' | Commercial Use Unlimited';
}
// Remove personal use if same price as commercial
if ($personal_use_price == $commercial_use_price) {
unset($license_options[PERSONAL_USE_LICENSE_ID]);
}
// Default value
$default_value = key($license_options);
// ---------------------------------------------------------------------------
// Build form
$form['license'] = array(
'#type' => 'radios',
'#options' => $license_options,
'#default_value' => $default_value,
'#required' => TRUE,
);
$form['personal_use_price'] = array(
'#type' => 'value',
'#value' => $personal_use_price,
);
$form['commercial_use_price'] = array(
'#type' => 'value',
'#value' => $commercial_use_price,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Download'),
'#attributes' => array(
'class' => array('ctools-use-modal'),
),
);
$form['#action'] = url('download-manager/nojs/download/122');
return $form;
}
?>
And here's my modal wizard callback that the form's action links to:
<?php
function download_manager_wizard($js = NULL, $nid = NULL, $step = NULL) {
// $user_id is used to create $download_object_id
global $user;
// Check for js
if ($js) {
ctools_include('modal');
ctools_include('ajax');
}
// Set up the ctools wizard
$form_info = array(
'id' => 'download_manager',
'path' => "download-manager/" . ($js ? 'ajax' : 'nojs') . "/download/$nid/%step",
'show trail' => TRUE,
'show back' => TRUE,
'show return' => FALSE,
'next callback' => 'download_manager_wizard_next',
'finish callback' => 'download_manager_wizard_finish',
'cancel callback' => 'download_manager_wizard_cancel',
'order' => array(
'choose-license' => t('Choose License'),
'confirm-spending' => t('Confirm Spending'),
'start-download' => t('Start Download'),
),
'forms' => array(
'choose-license' => array(
'form id' => 'download_manager_wizard_choose_license_form',
),
'confirm-spending' => array(
'form id' => 'download_manager_wizard_confirm_spending_form',
),
'start-download' => array(
'form id' => 'download_manager_wizard_start_download_form',
),
),
);
// Create our unique object id, for caching.
$download_object_id = $nid . '_' . $user->uid;
// TODO: This automatically gets defaults if there wasn't anything saved.
$download_object = download_manager_wizard_cache_get($download_object_id);
if (!isset($download_object)) {
// Create a default object.
$download_object = new stdClass;
$download_object->nid = $nid;
$download_object->license = 'unknown';
$download_object->price = 'unknown';
}
if (empty($step)) {
// We reset the form when $step is NULL because that means they have
// for whatever reason started over.
download_manager_wizard_cache_clear($download_object_id);
$step = 'choose-license';
}
// Set the form state
$form_state = array(
'ajax' => $js,
// Put our download_object and ID into the form state cache so we can easily find it.
'download_object_id' => $download_object_id,
'download_object' => &$download_object,
);
// Send this all off to our form. This is like drupal_get_form only wizardy.
ctools_include('wizard');
$form = ctools_wizard_multistep_form($form_info, $step, $form_state);
$output = drupal_render($form);
// Render the form in modal if js.
if ($js) {
// If javascript is active, we have to use a render array.
$commands = array();
if (!empty($form_state['cancel'])) {
// If cancelling, return to the activity.
$commands[] = ctools_modal_command_dismiss();
}
else {
$commands = ctools_modal_form_render($form_state, $output);
}
print ajax_render($commands);
exit;
}
else {
if (!empty($form_state['cancel'])) {
$original_node_path = 'node/' . $nid;
drupal_goto($original_node_path);
}
else {
return $output;
}
}
}
?>
I'm using this call to render the form:
<?phpprint drupal_render(drupal_get_form('download_manager_download_form', $node->nid));
?>
And like I said, I've tried ctools_modal_text_button, and that works fine to generate the modal:
<?phpprint ctools_modal_text_button(t('Download'), 'download-manager/nojs/download/122', t('Download this asset'), 'download-button');
?>
#4
Here's a screenshot of the error I'm getting (attached).
#5
Oops... realized that I left in the form_submit callback code for the error screenshot I attached previously (not sure if that really matters or not). Removed the submit callback, and the AJAX HTTP error message now reads as follows (looks like it's basically just spitting out the page content):
An AJAX HTTP error occurred.HTTP Result Code: 200
Debugging information follows.
Path:
StatusText: OK
ResponseText:
Euro Stamp Brad 1 | Pixel Scrapper
@import url("http://dev.pixelscrapper/modules/system/system.base.css?m13rw3");
@import url("http://dev.pixelscrapper/modules/system/system.menus.css?m13rw3");
@import url("http://dev.pixelscrapper/modules/system/system.messages.css?m13rw3");
@import url("http://dev.pixelscrapper/modules/system/system.theme.css?m13rw3");
@import url("http://dev.pixelscrapper/modules/contextual/contextual.css?m13rw3");
@import url("http://dev.pixelscrapper/modules/comment/comment.css?m13rw3");
@import url("http://dev.pixelscrapper/modules/field/theme/field.css?m13rw3");
@import url("http://dev.pixelscrapper/modules/node/node.css?m13rw3");
@import url("http://dev.pixelscrapper/modules/search/search.css?m13rw3");
@import url("http://dev.pixelscrapper/modules/user/user.css?m13rw3");
@import url("http://dev.pixelscrapper/sites/all/modules/views/css/views.css?m13rw3");
@import url("http://dev.pixelscrapper/sites/all/modules/ctools/css/ctools.css?m13rw3");
@import url("http://dev.pixelscrapper/sites/all/modules/ctools/css/modal.css?m13rw3");
@import url("http://dev.pixelscrapper/sites/default/modules/node_list/css/node-list.css?m13rw3");
@import url("http://dev.pixelscrapper/sites/all/modules/admin_menu/admin_menu.css?m13rw3");
@import url("http://dev.pixelscrapper/sites/all/modules/admin_menu/admin_menu.uid1.css?m13rw3");
@import url("http://dev....sis. Nunc vel imperdiet sem. Pellentesque consectetur egestas felis, id porta elit scelerisque et. Nullam a mauris dolor. Fusce leo augue, facilisis ut cursus nec, congue a augue. Nulla fermentum tristique nulla nec ullamcorper.
Follow Me
Blog
Facebook
Flickr
Pinterest
Twitter
YouTube
RSS Feed
RSS by Email
Configure block
Execute PHP Code
PHP code to execute
Enter some code. Do not use <?php ?> tags.
Configure block
Search form
Search
Configure block
Colors
tan, black
Tags
europe, stamp
File Info
png image, 0.5mb
600 x 600 pixels (1.7 x larger than shown)
2 x 2 inches
Description
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sollicitudin sapien non ipsum eleifend mattis. Donec sed turpis dolor. Sed rutrum lobortis ante, vehicula malesuada erat tincidunt id.
Download
FREE | Commercial Use Unlimited
Learn about our liberal licenses
Stats
15 Downloads
2 Lists
0 Comments
0 people heart this
Template File
Make your own assets like this one!
Get the template
Make your own assets like this!-->
jpg image, 0.1mb
500 x 500 pixels
Recent content
Configure block
Euro Stamp Brad 1Marisa Lerineditdelete
test templatemagjoreditdelete
Emmamagjoreditdelete
Bobmagjoreditdelete
Blue Corner Frame PaperMarisa Lerineditdelete
Jackmagjoreditdelete
test templatemagjoreditdelete
Red PaperMarisa Lerineditdelete
Busan Beach 1 - ribbonMarisa Lerineditdelete
Busan Beach PaletteMarisa Lerineditdelete
More
Configure block
Powered by Drupal
#6
Any chance of getting further help on this?
#7
I'm running into the same issue. I need to pass data from a form into a modal dialog, I took the same approach as you and getting the same error.
Any success yet?
#8
I got somewhat sidetracked from this issue, but no, still no luck. I'll post back here if I have an update, and would be grateful if you would do the same :)
#9
I encountered this issue while making a form, in which the email address is given, that opens another form in a modal, with the previously entered email already entered.
I found that in the file modal.js, in Drupal.behaviors.ZZCToolsModal, on line 224 findURL is used to get the url to use for the modal based on the button of the form.
This button however doesn't have the url information.
I don't know if this is the correct sollution, but if I add this check, that gets the action value of the parent form if no url was found. Patch is attached.
// AJAX submits specified in this manner automatically submit to the// normal form action.
element_settings.url = Drupal.CTools.Modal.findURL(this);
+ if (element_settings.url == '') {
+ element_settings.url = $this.parents('form').attr('action');
+ }
element_settings.event = 'click';
I also found a possible workaround. findURL tries to get a url based on the name of the item it is given. I added a hidden field to the form with a specific class and the url as value.
My submit butten name is submit, so the extra hidden field must have a class of edit-submit-url.
<?php$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
'#attributes' => array('class' => array('ctools-use-modal')),
);
$form['hidden_url'] = array(
'#type' => 'hidden',
'#value' => url('modal_url/nojs/parameter'),
'#attributes' => array('class' => array('edit-submit-url')),
);
?>
#10
#11
Thank you very much Sander for the extremely helpful reply--both of your solutions worked for me!
Regarding the patch:
So my version reads:
<?phpif (element_settings.url == '') {
element_settings.url = $(this).closest('form').attr('action');
}
?>
#12
Hey Sander, this is slightly off topic, but can you tell me how you managed to pass data from your form to the modal (you say you passed an email address)?
#13
#14
Any chance on getting further help with this? alduya, are you still there?
#15
Have been using #11 for some time without any problems. Any chance of getting this patched in dev?
#16
+1 to commit, really annoing
#17
I'm a little unsure about this patch. While it will AJAX to the form action, is it actually going to properly submit anything? Since it's acting on 'click' and not 'submit' I don't think it's going to submit form values, is it?
Plus, it's not RTBC if the actually attached patch isn't the patch that's been reviewed.
#18
Merlin: that's a good question about the form actually submitting anything. I've just been using this to pass values from a form to an ajax modal (just grabbing the values from $_POST)... haven't actually needed to submit the form, per say.
#19
Here is the patch from #11 as a patch. It solves the problem for me where we're submitting a VBO form, so I think it is find for submission, but wouldn't hurt to have some more testing...
#20
Also there's a question to properly process when form submission ends with redirect
#21
Yes, it varies depending on what's happening, so we deal with that in the submit handlers using the various core/ctools ajax commands.
#22
If the form is being submitted properly, then I think this is RTBC, as that's the only question that was holding it back...