Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
For those who are interested, I am posting here (I don't know if this is the right place) a solution to display webforms (webform.module) into the fabulous CTools modal window. The solution is based on the examples found in ctools_ajax_sample.module.
Comments and improvements (in particular regarding the display of node fields) are welcome.
In a custom module :
- Create a menu item pointing a page callback, say
ctools_ajax_content
through hook_menu similarly to example in ctools_ajax_sample.module. This menu path will be used as a link to open the webform. - Add a custom submit function to the webform that shall be displayed in the modal CTools window (through hook_form_alter), say
$form['#submit'][] = '_custom_webform_submit';
. This must run after the other submit function, so that it is called only when everything goes fine. - The menu callback function calls another function
ctools_ajax_modal_webform
that handles the display of the webform and the confirmation message after successful validation in the same CTools modal window. By doing so, you can use this function for different purposes (e.g. different webforms).
<?php // Menu callback function ctools_ajax_content($js = NULL) { $webform_nid = WEBFORM_NID; // Your webform $nid return ctools_ajax_modal_webform($js, $webform_nid); } // Handle CTools modal webforms // $webform_nid is the nid of the webform function ctools_ajax_modal_webform($js = NULL, $webform_nid = NULL) { $node = node_load($webform_nid); // Load webform node $submission = (object) array(); // empty object required by webform // React without the modal if (!$js) { // Webform requires more parameters than standard forms return drupal_get_form('webform_client_form_'.$webform_nid, $node, $submission); } // React with the modal // Add modal components ctools_include('modal'); ctools_include('ajax'); $form_state = array( 'title' => $node->title, 'ajax' => TRUE, ); // Emulate ctools_modal_form_wrapper() form modal.inc because webform can not be triggered trough drupal_build_form // If it can, I'd be glad to understand how $form_state += array( 're_render' => FALSE, 'no_redirect' => !empty($form_state['ajax']), ); // Fetch webform form stuff $output = drupal_get_form('webform_client_form_'.$webform_nid, $node, $submission); // Merge node content (except webform) and webform form before rendering $node_view = node_view($node); // Prepare webform for rendering $node_view['body']['#weight'] = -100; // Ensure node body is at the top unset($node_view['webform']); // Prevent displaying twice the webform array_unshift( $output['submitted'], $node_view['body']); // Merge $node->title = ''; // Remove title to prevent displaying twice if (!empty($form_state['ajax'])) { $output = ctools_modal_form_render($form_state, $output); } // Handle successful submission through session flag - see '_custom_webform_submit' function below if ( isset($_SESSION['webform_client_form_'.$webform_nid]) && $_SESSION['webform_client_form_'.$webform_nid] == 'submitted') { // Delete session flag unset($_SESSION['webform_client_form_'.$webform_nid]); // Fetch confirmation message. It will be displayed in the modal window $confirmation['#markup'] = '<div class="popups-confirmation-wrapper">'. check_markup($output['#node']->webform['confirmation'], $output['#node']->webform['confirmation_format'], '', TRUE). '</div>'; $output = array(); // Recreate output // Oerwrite the form output if it was successful. $output[] = ctools_modal_command_display('Confirmation', $confirmation); } // Render output in modal window print ajax_render($output); exit; } // Set a session flag to mark the webform as submitted. // This value will be used to trigger display confirmation message in CTools modal window function _custom_webform_submit($form, $form_state) { $webform_nid = $form['#node']->nid; $_SESSION['webform_client_form_'.$webform_nid] = 'submitted'; };?>
Laurent
Agence Web Coheractio
Comment | File | Size | Author |
---|---|---|---|
#26 | submit handler.png | 7.9 KB | msankhala |
Comments
Comment #1
mstrelan CreditAttribution: mstrelan commentedThis is a rather timely post as I was looking for the same thing. I don't think it's the right spot for it, but nonetheless here is some feedback.
1. It just prints out a JSON response, how do you link it up properly? Do you need something like ctools-use-modal?
2. What happens with the session variable if you want to submit the same webform twice. For example I have a form "enquire about this artwork" and the user might want to submit it for 5 different artworks.
Comment #2
Agence Web CoherActio CreditAttribution: Agence Web CoherActio commentedThe above function indeed need the ctools modal stuff around it as shown below.
With regards to the session variable, it is set when webform validates and immediately unset when displaying confirmation message, so that one can submit several time.
Code examples :
Menu item :
Load CTools modal stuff. I am using hook_init() because it is used on every page
Laurent
Agence Web Coheractio
Comment #3
mstrelan CreditAttribution: mstrelan commentedI found a new module Simple Dialog which does the trick for me.
Comment #4
JoshuaBud CreditAttribution: JoshuaBud commentedCurious the differences with D6 version of this sample code. I would love to implement with a D6 site and have a form popup to fill out.
Comment #5
Apfel007 CreditAttribution: Apfel007 commentedhow/what is the "_custom_webform_submit" calling?
It's called with this .. the only problem is, that $form['#submit'][] is not working ..?? do it now with $form['#submit'][2]...
Comment #6
Apfel007 CreditAttribution: Apfel007 commentedHow is the "function ctools_ajax_modal_webform" called the "second time" - for the confirmation message?
my _SESSION value has 'submitted' BUT the key seems to be empty.. should be : _SESSION['webform_client_form_'.$webform_nid]
but is :
_SESSION[]
and $form['#node']->nid doesn't exists... should be $form['#node']->vid ..??
Comment #7
Agence Web CoherActio CreditAttribution: Agence Web CoherActio commentedThe webform shall be set to "No redirect (reload current page)" so that it calls the form another time after submission.
In order to set the session value you need to add the custom validation function in hook_form_alter.
$webform_nid = $form['#node']->nid does exist (use devel and dpm($form) to see all data).
Note this code works only on D7.
Laurent
Comment #8
Apfel007 CreditAttribution: Apfel007 commentedwill try
Comment #9
lock2007 CreditAttribution: lock2007 commentedHi,
can you make a tutorial to make it easy for novice ?
Thanks a lot
Comment #10
msakurada CreditAttribution: msakurada commentedOK, I like the implementation, had some small issues but was able to power through them. Thanks!
Comment #11
carvalhar CreditAttribution: carvalhar commentedhi,
i'm using another module (Simple Dialog) and i got a different solution to the same problem with modal vs webform:
http://drupal.org/node/1241242#comment-5431176
Comment #12
wamilton CreditAttribution: wamilton commentedAsk and ye shall receive (months later).
Here it is in abbreviated form; I had no need of anything other than the actual form for my modal.
Setting the $form_state and calling ctools_modal_form_render doesn't affect anything other than the title.
Comment #13
Agence Web CoherActio CreditAttribution: Agence Web CoherActio commentedMany thanks Wamilton. l'll give a try.
In order to improve the solution further:
@carvalhar : does you approach work for multistep webform as well?
Many thanks for your feedback!
Laurent
Coheractio : Agence Web Paris Versailles
Comment #14
carvalhar CreditAttribution: carvalhar commented@Laurent_t i didn't try with multistep, but if form validation (i mean, a form is submitted and a new page is loaded inside the modal) plays nice, i think it will work fine with multistep also.
Comment #15
wamilton CreditAttribution: wamilton commented@Laurent:
What you get back from ctools_modal_form_wrapper (if it doesn't have messages to stop it) is an array of ajax commands for ajax_render(). You could just concatenate the drupal_render of the node body in its own div (if you need to style it differently) in the html of that command like this:
edit: also didn't try multi-step, but if it didn't work when you tried it before, there's reason to suspect that it may work if you render the form by correctly invoking ctools_modal_form_wrapper() since that actually sets the form_state in the way that the ctools form_wizard expects (except that it wants you to set $form_state['modal'] = TRUE but that's probably just how that tool expects things to be).
Comment #16
Agence Web CoherActio CreditAttribution: Agence Web CoherActio commentedGreat : many thanks to all of you.
Laurent
Coheractio : Agence Web Paris Versailles
Comment #17
merlinofchaos CreditAttribution: merlinofchaos commentedSo can this be marked fixed?
Comment #18
Agence Web CoherActio CreditAttribution: Agence Web CoherActio commentedDone.
If you think this is worth it, I can write a tutorial for this in the documentation section (actually I don't know if there is a section for ctools).
Comment #19
meghanmary CreditAttribution: meghanmary commentedI would love to see a tutorial.
Comment #21
osopolarThis still seems not to work for multistep forms. The result of multistep forms is held in $submission variable, which currently won't be set. Somehow we need to pass the $form_state array to ctools_ajax_modal_webform, but I can't see how.
See also:
Module Modal forms (with ctools): #1326716: Webform module support
#1168980: webform and ctools integration (duplicate of this issue)
Comment #22
qoomir CreditAttribution: qoomir commentedComment #23
wamilton CreditAttribution: wamilton commented@osopolar:
See #12: ctools_modal_form_wrapper() takes in form_state, you just need to put in the attributes it expects.
ctools_ajax_modal_webform() is just an example, you need to rewrite it to suit your actual use case. What exactly are you trying to do?
@qoomir:
You seem to have your site paths set up kind of funky: the path in your 404 error is not the same as the one in your hook_menu implementation. What happens if you add 'webdevelopers/' to the front of the path in hook_menu and disable the module and re-enable it?
Comment #24
osopolar@wamilton: I am exactly trying to show a multistep webform within CTools modal windows ;)
See Modal forms (with ctools) (which still needs this patch: #1326716: Webform module support).
Comment #25
rv0 CreditAttribution: rv0 commentedI'm doing something similar with http://drupal.org/project/ctools_automodal
and patch #1396272: Handle submitted forms
might be useful to someone: (simplified code)
In hook menu
In file custom.pages.inc, function custom_webform_form:
$form = drupal_get_form('webform_client_form_'.$nid, node_load($nid), (object) array(), '', '');
return $form;
This seems like a much simpler and shorter way to do it
Comment #26
msankhala CreditAttribution: msankhala commentedI tried this code and code in comment #12 but there is problem with this code. its not calling submit handler each time. I don't know why May be its some caching issue. I tried $form['#submit'][2] = '_custom_webform_submit'; also as suggested in comment #5 but that doesn't help. hook_form_alter is called each time and this hook_form_alter will attache custom submit handler to the webform. I confirmed this using chromephp and printing $form array. In $form['#submit'] it show the custom submit handler at index 2 but doesn't call that submit handler.
Comment #27
msankhala CreditAttribution: msankhala commentedNo reply :)
Finally i found the solution. Here the session variable is used to decide whether to show form or confirmation message. In my case the the custom submit handler is not called so session variable is not set. So it show the form again rather then confirmation message. In form_state array variable there is a index 'executed' which is set to true only if the form submitted successfully otherwise this variable is set to false. So using this variable it is possible to decide whether to show form or confirmation message. So there is no need to define form alter and custom submit handler and no need to set any session variable. Here is code:
Comment #28
muschpusch CreditAttribution: muschpusch commented#27 doesn't work!
#1326716: Webform module support does work
Comment #29
Ruslan CreditAttribution: Ruslan commentedSorry, but your code is wrong.
Function "ctools_modal_form_wrapper" doesn't return form with webform fields:
<form action="/modal_forms/ajax/test" accept-charset="UTF-8" method="post" id="webform-client-form-12" class="webform-client-form" enctype="multipart/form-data"> <div><input type="hidden" name="form_build_id" id="form-25af2969d9055c763f3fcabb7945c70c" value="form-25af2969d9055c763f3fcabb7945c70c" /> <input type="hidden" name="form_token" id="edit-webform-client-form-12-form-token" value="fe3a98ea09eba2e1f1a1d8d48e93702a" /> <input type="hidden" name="form_id" id="edit-webform-client-form-12" value="webform_client_form_12" /> </div></form>
Comment #30
Ruslan CreditAttribution: Ruslan commentedMy code for D6 (webforms + ctools modal window)
You can try.
Comment #31
anouHello,
Just to say that for multistep webform, you must change:
by
Thanks for your code.
Comment #32
Ruslan CreditAttribution: Ruslan commentedYea, you right
Comment #33
renesmee CreditAttribution: renesmee commentedhow to display webform in a popup window on clicking on a image?
Comment #34
Agence Web CoherActio CreditAttribution: Agence Web CoherActio commentedYou just need to add the class
ctools-use-modal
to your link.Laurent
Comment #34.0
Agence Web CoherActio CreditAttribution: Agence Web CoherActio commentedAdded php brackets for readability
Comment #35
agerard CreditAttribution: agerard commentedClueless question on an old post, from one who has not even written a module yet: where would one actually put this code? I.e. if one were trying to add a confirmation dialog to one of Drupal 7's node edit screens, how/where would one catch the interaction and change it? I've programmed Java apps, but I'm still learning php and working my way up to doing more at the code level in Drupal. I never seem to find explanations/tutorials that bridge the gap between building views and really using the API. With apologies for my ignorance, any pointers to resources in this area would be greatly appreciated!
Comment #36
panditvarun20 CreditAttribution: panditvarun20 commentedI have a filter form means with some check box and select list. I want to show them on pop up and after submit these checked values should be shown in a block.
How is it possible