Hi

I need to port a web form that connects to a remote service. The remote service can take up to 70 seconds to respond. Our standard web form is implemented using Javascript/AJAX/DHTML as follows

onsubmit: (assume the form is valid)
1) hide the form
2) display some sort of progress bar or busy animation
3) make an AJAX call to my remote service
4) if (remote service returned an error ) redisplay the form, along with the server error message
5) else display response from server.

I need to implement this in Drupal. For security reasons, we want to make the connection made from our Drupal server and not from the users web browser. I am having a lot of trouble. I based my code on the "ajax_example_submit_driven_ajax()" example. Maybe this was not a good example to start from?

Building the form and validating where easy, I can not get the ajax code to work the way I want. I do not know how to implement the "hide" in drupal so what I did was wrap the entire form, add my form elements. I added an extra "error box" element, and define the ajax. My idea was

a) when submit begins, disable the form elements (I could not figure out how to get this to work)
b) if I got an error back, enable the form elements, and display the remote server error in the "error box" element
c) if I got a result back, replace the entire form with the response from the remote service

function aedwip_registration_form_ajax($form, &$form_state) {

    // wrap the entire form, so we can replace it if we want
    $form['#prefix'] = "<div id='AEDWIP_REGISTRATION_WRAPPER'>";
    $form['#suffix'] = "</div>";

    $form['arg1'] = array(
    '#description' => t('pass this argument to the remote service '),
    '#required' => TRUE,
    '#type' => 'textfield',
    '#title' => t("Argument 1"),
    );
   ...

    // create an element to display errors from remote service
    $form['error_box'] = array(
    '#markup' => '',
    '#prefix' => '<div id="error_box">',
    '#suffix' => '</div>',
    '#type' => 'markup',
    );

    // I set the wrapper to the form id so that
    // I can replace the entire form if I get back a valid response
    // from the remote servcie
    $form['submit'] = array(
    '#ajax' => array(
        'callback' => 'AEDWIP_registration_submit_callback',
        'wrapper' => 'AEDWIP_REGISTRATION_WRAPPER',
        'name' => 'submit1',
        'method' => 'replace',
    ),
    '#type' => 'submit',
    '#value' => t('Submit'),
    );
    return $form;
}

function AEDWIP_registration_submit_callback($form, $form_state) {

        ??? how do I disable the form elements?

       get form arguments
       build up URL
       user curl to make request to remote service
       if ( $responseFromRemoteSerice has error) {
          how do I enable form
          $error_box = $form['error_box'];
          // this does not work
          $error_box['#markup'] = "Errors form remote service ";
         return form; // I want to display the form with the extra error message
       }
       else {
          return remote service result; // should replace the entire form
       }
    }

Comments

Jaypan’s picture

There is a lot of work going into what you do, and it's going to take you a lot of googling to figure out how to put it together.

What I would so is set your whole form up to be Drupal AJAX form - using the #ajax attribute of the Form API. Set your submit button up to be #ajax enabled. Once you have done this, when the submit button is clicked, it will not submit through a page reload, but rather submit through javascript to the server. The submission process on the server side however is the same as if it were submitted through a regular HTTP request, in that it will go through the applicable _validate() and _submit() functions for your form.

In the _validate() function, use drupal_http_request() to make the request to the external server. If any of the data comes back as invalid, you can at this point use form_set_error() to set an error on the form element in question. This will be returned through javascript to the form. This is all part of the #ajax mechanism.

So basically, you need to spend some time researching how to use Drupal's FormAPI's #ajax attribute, and how to use drupal_http_request(). Those two things will allow you to do what you need.

bangzippy’s picture

Hi Jay

thanks for the suggestion. I give it try tonight.

I thought "#ajax" only applied to form elements, I did not see anything in the form api http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.... that suggest its works on forms

If I understand your proposal you are suggesting something like

function aedwip_registration_form_ajax($form, &$form_state) {

    // wrap the entire form, so we can replace it if we want
    $form['#prefix'] = "<div id='AEDWIP_REGISTRATION_WRAPPER'>";
    $form['#suffix'] = "</div>";
    $form['#ajax'] = array (
       'callback' => 'AEDWIP_form_callback',
        'wrapper' => 'AEDWIP_REGISTRATION_WRAPPER',
        'name' => 'form',
        'method' => 'replace',
    );

  $form['submit'] = array(
    '#ajax' => array(
        'callback' => 'AEDWIP_registration_submit_callback',
        'wrapper' => 'AEDWIP_REGISTRATION_WRAPPER',
        'name' => 'submit1',
        'method' => 'replace',
    ),
    '#type' => 'submit',
    '#value' => t('Submit'),
    );
    return $form;

I'll let you know what I find out