2

I'm having a little problem with my drupal 7 module. I'm trying to get the $form_state['values'] from $form['base']['st-volume-pricing']['price'] and $form['base']['st-volume-pricing']['till-amount'] in my ajax callback so that I can add them to a results table.

Is this the right way to do it or am I missing something?

function mymodule_form_alter($form, &$form_state) { 
  $form['base']['st-volume-pricing']['price'] = array(
    '#type' => 'uc_price',
    '#title' => t('Price'),
    '#description' => t('Set the price for this volume\'s reduction'),
    '#size' => 10,
    '#prefix' => '<table id="volume-pricing-standard-input"><tr><td>',
    '#suffix' => '</td>',
  );
  $form['base']['st-volume-pricing']['till-amount'] = array(        
    '#type' => 'textfield',
    '#title' => t('Till Amount'),
    '#description' => t('The amount till which the volume discount applies'),
    '#size' => 10,
    '#prefix' => '<td>',
    '#suffix' => '</td>',
  );
  $form['base']['st-volume-pricing']['add'] = array(
    '#type' => 'submit',
    '#value' => t('Add'),
    '#submit' => array('mymodule_add_volume_standard'),
    '#ajax' => array(
      'callback' => 'mymodule_add_volume_standard_ajax_callback',
      'wrapper' => 'st-volume-results',
      'method' => 'append',
      'effect' => 'fade',
    ),
    '#prefix' => '<td>',
    '#suffix' => '</td></tr>',
    '#title' => t('Click this button to add a standard volume price'),
  );

  //this is our results table
  $form['base']['st-volume-pricing']['st-volume-results'] = array(
    '#type' => 'markup',
    '#markup' => '<table id="st-volume-results"><thead><tr><th>' . t('Price') . '</th><th>' . t('From Amount') . '</th><th>' . t('Till Amount') . '</th></tr></thead></table>',
  );
  variable_set('vol-st-price', NULL)
  variable_set('vol-st-from', 1)
  variable_set('vol-st-till', NULL)

  //this is our row that will be inserted
  $form['base']['st-volume-pricing']['st-volume-results']['row'] = array(
    '#type' => 'markup',
    '#markup' => '<tr><td>' . variable_get('vol-st-price') . '</td><td>' . variable_get('vol-st-from') . '</td><td>' . variable_get('vol-st-till') . '</td></tr>',
  );
}

When I'm using it inside here:

function mymodule_add_volume_standard_ajax_callback($form, &$form_state) {
  //check if there is a previous volume price and set the from field
  if (variable_get('vol-st-till') !== NULL) {
    variable_set('vol-st-from') = variable_get('vol-st-till') + 1;
  }; 
  //add or overwrite the value entered in price
  variable_set('vol-st-price') = $form_state['values']['base']['st-volume-pricing']['price'];
  //add or overwrite the value entered in till
  variable_set('vol-st-till') = $form_state['values']['base']['st-volume-pricing']['till-amount'];
  //create new row in results table
  return $form['base']['st-volume-pricing']['st-volume-results']['row'];
}

drupal_set_message("<pre>" . print_r($form_state['values']) . "</pre>"); displays 1.

I suppose that $form_state['values'] should only work during the submission of a form. How would one go about doing this when using a hook_form_alter() and ajax callbacks?

I also tried displaying drupal_set_message("<pre>" . print_r($form_state['values']) . "</pre>"); in my function mymodule_add_volume_standard. Which also displayed 1. Neither does it work when trying it in the hook_form_alter() which is default behaviour I suppose?

I'd really appreciate it if someone could clarify some things for me.

1

Some basics:

function mymodule_form_alter($form, &$form_state) {
  1. hook_form_alter is a generic alter function that receives a third argument $form_id to distinguish the possible forms. Right now you would alter every form in your site.

  2. The correct function signature is:

    function mymodule_form_alter(&$form, $form_state, $form_id) {
    

    You can see, that the $form itself is passed as a reference and can be changed. There is no way of changing $form_state directly during the form building process, which is when hook_form_alter is invoked.

Concerning $form_state['values'] in validation and submit handlers: All elements defined in the $form array are by default inserted into a flat structure in $form_state['values']. This means that with your setup, you would access the value entered in $form['base']['st-volume-pricing']['till-amount'] as $form_state['values']['till-amount']. You can change that behavior by defining #treefor the form element's parent, see for example: https://drupal.org/node/48643

Edit: The general approach for ajax forms is that in the submit you store values inside $form_state, e.g. in $form_state['storage'], set $form_state['rebuild'] which assures that the form builder and hence your alter function is called again, and then test for the presence of stored values inside your form alter function. Depending on the submitted values you would then implement the logic to achieve what you want.

| improve this answer | |
  • 1. my bad I meant I'm using: hook_form_FORM_ID_alter() instead. 2. Yes I understood that part. Thank you for confirming. I shall have a look at the reference you gave and report back. Thank you for the help. – Simbaclaws Jan 27 '14 at 13:36
  • @Simbaclaws I have updated the answer regarding ajax. – berliner Jan 27 '14 at 13:40
  • Thank you!! It works! I'll update the solution in a short while. I still have to find a way of validating user input through the callback. – Simbaclaws Jan 27 '14 at 14:32
  • @Simbaclaws The validation would be done in a validation handler, not in the callback. Form processing is essentially the same as with non-ajax forms. Check this doc if you don't know it yet: drupal.org/node/752056 – berliner Jan 27 '14 at 14:39

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.