You can add some custom value to the form_state
and use it to determine whether to build a new form element or not. Please try the following example:
/**
* An example form.
*/
function example_form($form, &$form_state) {
$form['#tree'] = TRUE;
// Use this value to determine whether to build a new form element or not.
if (empty($form_state['add_new_item'])) {
$form_state['add_new_item'] = FALSE;
}
$form['example_fieldset'] = array(
'#type' => 'fieldset',
'#title' => t('Example form'),
// Set up the wrapper so that AJAX will be able to replace the fieldset.
'#prefix' => '<div id="example-fieldset-wrapper">',
'#suffix' => '</div>',
);
$form['example_fieldset']['name'] = array(
'#type' => 'textfield',
'#title' => t('Name'),
'#required' => FALSE,
);
$form['actions'] = array(
'#type' => 'actions'
);
// add field button.
$form['actions']['add_field'] = array(
'#type' => 'submit',
'#value' => t('Add new form item'),
'#submit' => array('field_add_one'),
'#ajax' => array(
'callback' => 'example_form_callback',
'wrapper' => 'example-fieldset-wrapper',
),
// hide this form element
'#attributes' => array(
'class' => array('element-invisible')
)
);
// submit button.
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit')
);
$form['#attached']['js'] = array(
array(
'type' => 'file',
'data' => drupal_get_path('module', 'YOUR_MODULE') . '/js/add_field.js',
),
);
// append a new form element (after ajax)
if ($form_state['add_new_item'] == TRUE) {
$form['example_fieldset']['new_item'] = array(
'#type' => 'textfield',
'#title' => 'My new item',
);
}
return $form;
}
/**
* Submit handler for the "add-field" button.
*
* - set the $form_state['add_new_item'] as TRUE.
* - rebuild the form.
*/
function field_add_one($form, &$form_state) {
$form_state['add_new_item'] = TRUE;
$form_state['rebuild'] = TRUE;
}
/**
* Ajax callback.
*
* Returns the fieldset with all values in it.
*/
function example_form_callback($form, &$form_state) {
return $form['example_fieldset'];
}
/**
* Final submit handler.
*
* Reports what values were finally set.
*/
function example_form_submit($form, &$form_state) {
$output = $form_state['values']['example_fieldset'];
drupal_set_message('<pre>' . print_r($output, true) . '</pre>');
}
add_field.js
(function($) {
Drupal.behaviors.your_module_name = {
attach:function() {
var form = $('#example-form');
// the 'add-field' form element
// this form element is invisible. It will be triggered by the custom link (not form element).
var addField = $('#edit-actions-add-field');
// add an example link
$('#my-custom-link').remove(); // prevent from adding the custom link more than once
form.after("<span id='my-custom-link'><a href='#'>ADD FIELD</a></span>"); // add custom link
// Attach mousedown() to the custom link in order to activate ajax.
// Notice: You can attach click() to a normal submit form element (without ajax)
// but it has to be mousedown() if the form element has an ajax attribute.
$('#my-custom-link').click(function() {
addField.mousedown();
});
}
};
}(jQuery));