0

I have a link in a block and when i click it it brings with ajax a form from another page let's call it contact. In contact page the form uses ajax to submit the data, it works ok. But when i get the form by clicking that link in another page using ajax the form loses the ajax submit. and instead it redirects me to the contact page.

How can i keep the ajax submit even if the form loads with ajax in another page???

2

It seems, I found some solution, may be not fully drupal-way.

Firstly, we need to load JS libraries, needed for working of ajax submit. This code helps us:

drupal_add_library('system', 'drupal.ajax');
drupal_add_library('system', 'drupal.form');
drupal_add_library('system', 'jquery.form');
drupal_add_library('system', 'druapl.progress');
drupal_add_library('system', 'drupal.textarea');

Nextly, we need to fill JS class Drupal.settings.ajax with data about page elements, which provides ajax behavior. I have not an universal solution, I only stops JS code on breakpoint in misc/ajax.js when running it on page with correct working ajax form. You can see correct values in this part of code:

Drupal.behaviors.AJAX = {
  attach: function (context, settings) {
    // Load all Ajax behaviors specified in the settings.
    for (var base in settings.ajax) {
      if (!$('#' + base + '.ajax-processed').length) {
        var element_settings = settings.ajax[base];

        if (typeof element_settings.selector == 'undefined') {
          element_settings.selector = '#' + base;
        }
        $(element_settings.selector).each(function () {
          element_settings.element = this;
          Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
        });

        $('#' + base).addClass('ajax-processed');
      }
    }

So, in my case resulting JS code, needed to be added into startup javascript, looks like this:

if(Drupal.settings.ajax == undefined){
    Drupal.settings.ajax = {
        'edit-submit': {
            callback: "faqform_ajaxsubmit",
            event: "mousedown",
            keypress: true,
            prevent: 'key',
            submit: {
                _triggering_element_name: "op",
                _triggering_element_value: "Send"
            },
            url: 'system/ajax',
            wrapper:'submit-message'
        }
    };
}

If all done correctly, you form, loaded by ajax, will have correct ajax behavior, in my case - ajax submit.

May be there are more graceful solutions, may be diving deeper into code will help you to find them.


So, here is much more graceful solution!

After some analyses of steps, maked above, I decided, that only thing we need to make ajax form, loaded by ajax, to work is fill javascript Drupal.settings array with correct data, describing forb behavior. In the above example we made it by hands, with hardcode, whitch is not true. Obviously, somewhere in drupal code it work does automatically. I found this place. It is function ajax_pre_render_element in the ajax.inc. It gives array of any form element with ajax property and appends to it additional parameters, which will be converted to JS code and added to Drupal.settings array later. Exactly thing, that we need.

Here is my code now:

function anyform_block_info() 
{
    //standart form for displaying to user
    $blocks['any_form'] = array(
        'info' => t('Any form'),
        'status' => true,
        'region' => 'content',
        'weight' => 99,
        'visibility' => 1
    );
    //hidden 'form' needed to generate and load ajax behavior settings before form loading
    $blocks['faq_form_hidden'] = array(
        'info' => t('Any fake form'),
        'status' => true,
        'region' => 'footer', //I thing, it will be better place it in footer^ in my case content is ajaxed
        'weight' => 99,
        'visibility' => 1
    );
    return $blocks;
}

function anyform_block_view($delta) 
{
    switch ($delta) {
        case 'faq_form':
            $block['content'] = drupal_get_form('anyform'); //standart form
            return $block;
        case 'faq_form_hidden':
            $block['content'] = anyform_get_hidden_form(); //fake form
            return $block;
        break;
    }
}

function anyform_get_hidden_form()
{
    $form = drupal_get_form('faqform'); //give our original form
    $form = ajax_pre_render_element($form['submit']); //create settings for element with #ajax property (don't pass whole form as argument - not works)

    //makes fake form with hidden element in footer, but with correct array with settings for ajax behavior
    $fakeform['fakeform'] = array(
        '#type'=>'markup',
        '#markup'=>'<div style="display: none;"></div>',
        '#attached'=>$form['#attached'], //our magical array
    );

    return $fakeform;
}

So, I hope, it will solve most of your problems with drupal ajax-loaded forms. For me this solution works without any problems, and I going sleep being happy =^_^= Good luck!

| improve this answer | |
  • Thank you for sharing your code. I'll try this when i find some time and then I'll post back the results – dianikol Mar 16 '12 at 0:17
  • Disadvantage of this approach is that you always need to rewrite your php form code to js code. For example, if you need to add any settings to form... you need also add it in you js hack code =\ Sure, it is not true way... – ASGAlex Mar 17 '12 at 17:30
  • Hmm, it seems, that I found one good solution - post updated. Hope, it helps =) – ASGAlex Mar 21 '12 at 22:47
  • It seems that ajax_pre_render_element() is the key. Right? Is it necessary to create the $fakeform array? Isn't enough just to return the $form variable? – dianikol Mar 22 '12 at 16:47
  • Yes, it is necessary, because something HTML with javascript bindings must be rendered. If nothing will be rendered, needed drupal libraries will not be loaded, needed javascript settings will not be created, and when your form will be loaded, behaviors will not be attached. In my case ajax form is shown only in one page, which is loaded by ajax. On all other pages the fake form is shown. Advantages? You have clean pages without a lot of hidden and may be not needed content. Forms are loaded only when needed, not always. – ASGAlex Mar 22 '12 at 20:30
1

Ah.

It's a DOM thing. When you get the new contact form back (rendered via AJAX), then you have to tell the new button (in that rendered block), to issue another AJAX request -- otherwise it does it's default behavior.

-- EDIT --

What you do is embed a tag IN the form itself. When that form gets called into the DOM (via the AJAX call), the script should re-instantiate the button as an ajax button. In jquery:

<script>
$().ready(function(){
    $('.button').click(function(){
        // submit form via AJAX
        return false;
    });
)};
</script>
| improve this answer | |
  • 1
    Yes that makes sense. The problem is how can i do that in a form since it uses form api to add ajax functionality. For example in this form i have a field that when i click it a calendar pops up no problem because i use Drpal.attachBehviours in my js file. What is the way to do that in a form button? – dianikol Sep 23 '11 at 4:33
  • edited my reply – jhchnc Sep 23 '11 at 14:55
  • Of course i will mark your answer!! But the form submits using the '#ajax'property when i built the form. So the javascript is handled by drupal itself. I'm not sure what ajax call i should put in the sript above. Here you can see what's going on here Just the click the link at the top "Click me" to see it in action – dianikol Sep 23 '11 at 16:03
0

I've run into this problem before...I was able to get it working by loading the form in an i-frame that is in the modal window. You can set a redirect with some simple javascript in the header of the from. Doing it this way will also keep the error messages in the modal box if the form doesn't validate.

| improve this answer | |
  • Thank you for your answer. I don't think iframes used for this purpose anymore.There is got to be a native solution for this.. – dianikol Sep 24 '11 at 7:25
0

developed a custom module to make ajax things easier.. with this module you can load any pages without breaking its ajax or any other javascript/jquery functionality , this is done using Drupal.attachBehaviors .

here is the module (currently under review process)

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.