0

This question already has an answer here:

I am newbie into Drupal.

I want to add 2 form elements dynamically to existing form via AJAX based on particular condition. But in the examples I saw till now the AJAX callback defined returns only one element to form. I tried to achieve this by adding these two fields in fieldset and returning fieldset as a single item. But this replaces my container div completely. This works only at first time and then the contents returned by callback replaces the container.

function new_registration($form, &$form_state) {
    $form['select-reason'] = array(
        '#type' => 'select',
        '#title' => t('Reason'),
        '#options' => array('' => 'Select') + _global_reasons(),
        '#description' => t('Reason.'),
        '#ajax' => array(
          'event' => 'change',
          'callback' => 'is_true',
          'wrapper' => 'options',
          'method' => 'replace'
        ),
      );

    $form['options'] = array(
        '#type' => 'container',
        '#prefix' => '<div id="options">',
        '#suffix' => '</div>'
      );
    }

function is_true(&$form, &$form_state) {
      $product_quality = $form_state['values']['select-reason'];
      if(_belongs_check($product_quality)) {
          $form['a-add'] = array(
              '#type' => 'fieldset',
              '#collapsible' => FALSE,
              '#collapsed' => FALSE,
          );
          $form['a-add']['detail'] = array(
              '#type' => 'textfield',
              '#title' => t ( 'Details' ),
              '#description' => t ( 'Enter product name.' ),
              '#maxlength' => 400,
              '#size' => 100,
              '#required' => TRUE,
          );
          $form['a-add']['num'] = array(
              '#type' => 'textfield',
              '#title' => t ( 'Number' ),
              '#description' => t ( 'Enter number.' ),
              '#maxlength' => 400,
              '#size' => 100,
              '#required' => TRUE,
          );
      } else {
            //remove 2 fields added in IF block
      }
      return $form['a-add'];
    }

I also tried to return HTML structure of these two and place it in #markup type of form element. But I am not convinced with this way as theming might be complicated. Can anybody help? Thanks in advance.

marked as duplicate by Mołot, kenorb, Krishna Mohan, Yusef Mohamadi, Scott Joudry Jan 4 '16 at 14:43

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • have you tried this form['#state']? – Shabir A. Dec 30 '15 at 14:06
  • @ShabirA. Can't use form['#state'] as condition avaluation is done at server side and Ajax is used for it. – meen Dec 31 '15 at 5:12
0

You need to change the AJAX method from replace to html, so that the container won't be replaced by the ajax callback, instead the content of the container will be updated.

Please update your code as follows:

$form['select-reason'] = array(
  '#type' => 'select',
  '#title' => t('Reason'),
  '#options' => array('' => 'Select') + _global_reasons(),
  '#description' => t('Reason.'),
  '#ajax' => array(
    'event' => 'change',
    'callback' => 'is_true',
    'wrapper' => 'options',
    'method' => 'html', // Update this line
  ),
);
  • This resulted in "<div id="options"><div></div><div id="claim-options"><fieldset class="panel panel-default form-wrapper">". Its strange. If I remove #prefix and #suffix options from fieldset, it replaces whole wrapper and no div with Id "options" is visible. and If I keep the #suffix and #prefix I get two divs with id "options" – meen Dec 31 '15 at 4:58
  • Could you please check changing the ajax method from replace to html, leaving the rest of the code as in your question? So that it reads: $form['select-reason']['#ajax']['method'] = 'html'; – Елин Й. Dec 31 '15 at 8:32
0

Add the additional form elements in the build function. The build function is rerun on every ajax request. If you don't have other things to do as modifying the form structure, then the ajax callback can be empty and you only need to return the new ajax container.

So you need to change this:

Put the new form elements inside the ajax container (in the first function):

$form['options']['a-add'][...]

And then return the whole container in the ajax callback (second function):

return $form['options'];

You always have to return the outside ajax div, otherwise the ajax callback will not work a second time.

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