0

I have a fieldset with one field by default. I want to add new fields by ajax (button "new item"). I can do it for usual field, but I have a problem with fieldsets. How to do that?

For usual fields I do it like below:

$form['add_item'] = array(
    '#type' => 'button',
    '#value' => t('Add item'),
    '#ajax' => array(
        'wrapper' => 'content',
        'callback' => 'add_more_ajax',
        'method' => 'append',
        'affect' => 'fade',
    ),
);

function add_more_ajax($form, &$form_state) {
    $form['image'] = array(
        '#title' => t('Image'),
        '#type' => 'managed_file',
        '#default_value' => '',
        '#upload_location' => 'public://images/',
    );
    return $form['image'];
}
3
  • Please post your code: how are you doing it without fieldset, how with fieldset, and what way it fails.
    – Mołot
    Commented Jul 11, 2013 at 12:45
  • OK, I edited my question. I don't have code for fieldsets, because I really don't know how to do it. I can't just return $form['images'][] ;).
    – deem
    Commented Jul 11, 2013 at 12:56
  • Your luck - I'm writing the same just now.
    – Mołot
    Commented Jul 11, 2013 at 12:58

1 Answer 1

1

First - ajax callback should not make any persistent changes to $form. It's only duty is to return proper part of form array. Render all elements in form creation function:

mymodule_form($form, &$form_state) {
  $form['image'] = array (
    '#type' => 'fieldset',
    '#title' => t('images'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#prefix' => '<div id="product_images">',
    '#suffix' => '</div>',
  );
  if (empty($form_state['image']['count'])) {
    // Keep number of fields either in form or form state, both works.
    $form_state['image']['count'] = 4; // Default number of elements
  }
  elseif( isset($form_state['triggering_element']) 
      and $form_state['triggering_element']['#machine_name'] == 'more_images_button' ) {
    // If form was triggered by proper form element, increase counter
    $form_state['image']['count']++;
  }
  // Loop to create elements
  for ($i = 0; $i < $form_state['image']['count']; $i++) 
  {
    $form['image'][$i] = array (
      '#markup' => "<p>$i</p>",
    );
  }
  // And our button
  $form['image']['more'] = array (
    '#type' => 'button',
    '#value' => t('More'),
    '#ajax' => array (
      'callback' => 'product_more_images',
      'wrapper' => 'product_images',
      'method' => 'replace',
      'effect' => 'fade',
      'prevent' => 'submit',
    ),
    '#machine_name' => 'more_images_button',
  );
}

// Now callback function is trivial
function product_more_images($form, $form_state) {
  return $form['image'];
}

Of course it's only a sketch, with all off topic parts removed.

2
  • Thanks. What is the triggering_element ?
    – deem
    Commented Jul 11, 2013 at 13:15
  • 1
    @daroPL element that triggered this form assembly function?..
    – Mołot
    Commented Jul 11, 2013 at 13:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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