I have a regular Drupal form that is not in a modal. When the user submits the form, a modal popup opens (as in http://drupal.org/node/1482968).

My question is, what is the best method for passing form input to the modal? So that e.g. if the user enters their name ("Alex") in the form, the modal popup can read, "Welcome Alex!" ?

Comments

JordanMagnuson’s picture

Any chance on getting some help with this? I'd really appreciate it!

JordanMagnuson’s picture

Tried posting this to Drupal Answers as well, but still no help :( . Any guidance would be wonderful.

andypost’s picture

Status: Active » Fixed

Suppose you should use session variable because form_state is cleaned after submit, another way to use ctools object cache

JordanMagnuson’s picture

Thanks a lot for the reply Andrey! Could you elaborate a little on which solution you think is better, and how to go about implementing it?

Perhaps it would be helpful if I described my situation a bit more: basically, every node on my site (several thousand nodes) can be downloaded, and so every node has a download form, where the user can select "personal use license" or "commercial use license" and then click download (submit the form). When the form is submitted a ctools modal pops up, asking the user for some more information based on the license that they selected.

So in other words, data needs to be cached/passed to the ctools modal on a per-user, per-node basis (as every user can download multiple nodes, selecting a license for each one). Would a session variable or ctools object cache make more sense for this type of scenario?

andypost’s picture

@JordanMagnuson As I understand you right you just need to pass a few values to modal, so You does not need a cache, just pass this values within URL to modal.

JordanMagnuson’s picture

Then I would need to use $form_state['redirect'] in my form submit handler, correct (in order to get the chosen value into the url)? Is this good form?

Thanks for all your help! Really appreciate it!

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

JordanMagnuson’s picture

Status: Closed (fixed) » Active

Yikes, I know it's been a long time since this issue was active... I got hauled off to a different project, and neglected to get this resolved. Anyway, I'm back on this issue now, and am still having trouble.

Anyway, with regards to passing simple form input to a modal popup, passing the value from the form to the modal via url seems like the obvious thing to do; however, the only way I know to accomplish that is via $form_state[''redirect'] in the form's submit handler (as in http://drupal.stackexchange.com/a/34756/3370). I can successfully redirect the form that way, and get the input, but the problem is that the modal popup is not used (as far as I know it would be impossible to invoke a modal via redirect?).

So I'm kind of stuck...

1. Within the original form declaration function I can get the modal to open on submit, but have no access to user input...

2. Within the submit handler I have access to user input, but cannot get a modal to open...

Any further help on this would be really, really appreciated! Thanks so much!

JordanMagnuson’s picture

Title: Passing form input to modal popup » [$25 bounty] How to pass form input to modal popup

Since this has been in the issue queue for a while... I'm happy to offer $25 to anyone who can provide a solution this issue.

JordanMagnuson’s picture

Title: [$25 bounty] How to pass form input to modal popup » How to pass form input to modal popup

Okay, I've solved this by simply accessing $_POST from within my modal, and grabbing the relevant form input from there. Not sure if that's the best solution, but it's working for now.

If someone within more Drupal / ctools knowledge can let me know if this is the best solution, I would be grateful. For now I'll leave this issue active.

acb’s picture

I too could use an answer on this... I can't even get page values in $_POST as per the above. I just see the page elements.

merlinofchaos’s picture

Status: Active » Fixed

Part of the issue here is that you're not really communicating 'to the modal'.

What you're doing is submitting a form, and having the response to the form open up the modal.

You can have a form submit to something and open up the modal for you simply by adding the class 'ctools-use-modal' and potentially setting a URL if it's not the form action. See ctools_ajax_sample_ajax_button_form() for more detail there. However, that example just goes to a form wizard.

The way you respond while using data is to go ahead and go through the normal drupal_build_form process; then afterward you can examine $form_state for any data that was in the form, including $form_state['values']. You can use that to render your page, and render a modal using ajax_render and ctools_modal_command_display() to actually tell it what to display in the modal.

acb’s picture

Thanks Merlin, for the answer.

But in my case I am not submitting; just hitting a chaos-tools link.

What you suggest might work, however, my usecase is this: trying to create a node-preview on a node-add form (without having to go through the submit/validation). I had planned to get the existing node form values, and create a preview of the node that way. Am I barking up the wrong tree here?

merlinofchaos’s picture

You need a button if you want values from the form; you can't easily get them just by clicking a link.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

JordanMagnuson’s picture

Hm... My method of grabbing the form data from $_POST (#10 above) appears to be flawed: in some rare instances, for some users, the modal seems to open before the data from the form has posted, so that $_POST is empty when the modal tries to retrieve the form data.

merlinofchaos: could you provide a bit more information about the method you advocate in #12? Perhaps a bit of pseudo-code? My understanding, from what you've posted, is that instead of opening a modal via the form action url, I should instead do the necessary work in the form's submit function (where form_state will have the submitted form values): check if js is enabled, and if it is use ajax_render and ctools_modal_command_display to open the modal directly; or else if js is not enabled, redirect...

Do I have the right idea there? If so, it seems the biggest change is that I won't be able to use my current modal callback any more... instead, I'll have to do the various logic contained in that function within my form submit function instead...

JordanMagnuson’s picture

Status: Closed (fixed) » Active
JordanMagnuson’s picture

JordanMagnuson’s picture

So this is sort of the idea I had, but I guess it's wrong, because it's not working :)

function my_form_submit($form, &$form_state) {
  ctools_include('modal');
  ctools_modal_add_js();
  $commands = ctools_modal_command_display('test', 'testing');
  print ajax_render($commands);
  exit;
}

Any help?

JordanMagnuson’s picture

I know it's been a while, but I'm still struggling with the best way to do this.

Would really appreciate any help/guidance. How should I open a modal after form submission?

eric.chenchao’s picture

Here is the small example. I have not tested myself though.


function mymodule_menu(){
  $items['myform_modal_url/%ctools_js'] = array(
      'title' => 'Welcome',
      'page callback' => 'myform_modal_callback',
      'page arguments' => array(1),
      'access callback' => TRUE,
      'type' => MENU_CALLBACK,
  );
}

function mymodule_myform($form, &$form_state) {
  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('name'),
    '#required' => TRUE,
  );

  ctools_include('modal');
  ctools_include('ajax');
  ctools_modal_add_js();

  $modal_style = array(
    // See modal example
  );

  drupal_add_js($modal_style, 'setting');

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Say hello'),
    '#id' => 'submit-btn',
  );

  $form['submit_url'] = array(
    '#type' => 'hidden',
    '#value' => url('myform_modal_url/nojs'),
    '#attributes' => array('class' => array('submit-btn-url')),
  );

  return $form;
}

function mymodule_myform_submit($form, &$form_state) {
  $form_state['rebuild'] = TRUE;
}

function myform_modal_callback($js = NULL) {
  if ($js) {
    ctools_include('modal');
    ctools_include('ajax');

    $form_state = array(
      'ajax' => TRUE,
    );

    $output = ctools_modal_form_wrapper('mymodule_myform', $form_state);

    if (!empty($form_state['executed'])) {
      $name = $form_state['values']['name'];
      $message = t('Welcome @name', array('@name' => $name));
      $output[] = ctools_modal_command_display(t('Welcome'), '<div class="modal-message">' . $message . '</div>');
    }
    else {
      // Add code here to handle validation error for example name is a required field.
      // Considering, this submission is via AJAX,
      // you may have to generate part or whole form and use 
      // ajax_command_replace() to replace it, which quite likes '#ajax' behavior of form.

      // Rendered HTML of myform with error class.
      // $data = $output[0]['output'];
      // $output[] = ajax_command_replace('myform-wrapper', $data);
    }

    print ajax_render($output);
    exit;
  }
}

Use ctools_modal_form_wrapper or drupal_build_form to build your submitted form and get your wanted field value from $form_state.

Hope it help.

JordanMagnuson’s picture

Thanks Eric! I really appreciate your taking the time to provide the example--it is super helpful.

What I'm not clear on from your example is how we get from the form to the modal callback...? I see the hidden [submit_url] field, but as far as I can tell that callback is never actually invoked anywhere. I see that when the form is submitted it is rebuilt... but what is going to make the actual modal pop up?

JordanMagnuson’s picture

To answer my own question in #22, this is handled "magically" by ctools based on "submit-btn-url" being defined for the form.

mikeytown2’s picture

Issue summary: View changes

I was attempting to get this working as well. I put together this hacky javascript but the button press ctools trigger doesn't get the latest href so it doesn't work. It adds the input value as another arg to the URL; close but no go. We'll end up doing this a different way now.

var input= document.getElementById('edit-user-email-address');
var link= jQuery('#edit-invite-user-send-email a[href].ctools-use-modal');
var old_href = link.attr('href');
input.onchange=input.onkeyup= function() {
  link.attr("href", old_href + '/' + encodeURIComponent(input.value));
};
darrenwh’s picture

Status: Active » Closed (works as designed)