0

I have an ajax callback function:

function mymodule_callback($form, &$form_state) {   
    $nid = $form_state['build_info']['args'][0]->nid;
    $node = node_load($nid);

    module_load_include('inc', 'node', 'node.pages');
    $form = node_page_edit($node);
    return print_r($form, true);       
}

(Please note that I'm returning from print_r as I'm trying to debug the problem).

This callback is being run from a form submit:

function mymodule_form_{my_form_id}_alter(&$form, &$form_state, $form_id) {
    $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => 'save',
        '#ajax' => array(
            'wrapper' => 'my-form-id',
            'method' => 'replace',
            'callback' => 'mymodule_callback',
            'effect' => 'fade'
        ),
        '#submit' => array('node_form_submit'),
    );       
}

When I submit the form I get an AJAX error which says 'cannot unset string offsets' in field.default.inc. I know that the node_page_edit function is causing it because when I remove it the error doesn't happen.

Interestingly, if I press the submit button again straight after getting this error, it works - and the full structure of the form is loaded in to my div.

Why doesn't it work the first time and how do I fix it?

0

My solution:

/* Drupal caches all ids of form elements and when ajax request happen, this
 * results in the new form have id's appended with --2 --3 etc, so css breaks.
 * Unsetting this makes the ids always the same. Maybe hook_init is not the best
 * place for this, but for now it works.
 */
function mymodule_init() {
    if(isset($_POST['ajax_html_ids'])) {
        unset($_POST['ajax_html_ids']);
    }
}

function mymodule_form_{my_form_id}_alter(&$form, &$form_state, $form_id) {    
    //only do the do if this is and ajax request   
    if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
        $form['actions']['submit'] = array(
            '#type' => 'submit',
            '#value' => 'Save',
            '#ajax' => array(
                'wrapper' => 'my_form_id',
                'method' => 'replace',
                'callback' => 'mymodule_callback',
                'effect' => 'fade'
            ),
            '#submit' => array('node_form_submit'),
        );

        /* For some reason this _has_ to be in form_alter. Putting it in a submit
         * callback doesn't work. What this is doing is setting the changed time
         * of the form to be in the future, if we don't do this, when the form is
         * reloaded after a submit, it's not possible to submit the reloaded form
         * because Drupal thinks someone else has edited it (I think it checks
         * the last update time of the node VS this value). This adds a 5min window
         * where changes can still happen. It's not the best solution but I think
         * it will work.
         */        
        $form['changed']['#default_value'] = time() + 300;
    }
}

function mymodule_callback(&$form, &$form_state) {      
    $new_form = drupal_rebuild_form('my_form_id', $form_state, $form);
    $form_html = drupal_render($new_form);

    return $form_html;
}

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.