Para ter um exemplo de código simples e funcional:
function MYMODULE_MYFORM($form, &$form_state) {
// #tree will ensure the HTML elements get named distinctively.
// Not just name=[name] but name=[container][123][name].
$form['#tree'] = TRUE;
if (empty($form_state['number_names'])) {
$form_state['number_names'] = 1;
}
for ($i = 1; $i <= $form_state['number_names']; $i++) {
$form['container'][$i] = array(
'#type' => 'container',
);
$form['container'][$i]['name'] = array(
'#type' => 'textfield',
'#attributes' =>array('placeholder' => t('Name')),
'#size' => 20,
'#required' => TRUE,
);
}
$form['add_item'] = array(
'#type' => 'submit',
'#value' => t('Add another name'),
'#submit' => array('MYMODULE_MYFORM_add_item'),
);
if ($form_state['number_names'] > 1) {
$form['remove_item'] = array(
'#type' => 'submit',
'#value' => t('Remove latest name'),
'#submit' => array('MYMODULE_MYFORM_remove_item'),
// Since we are removing a name, don't validate until later.
'#limit_validation_errors' => array(),
);
}
// $form['submit'] = array(
// '#type' => 'submit',
// '#value' => 'Submit',
// );
return $form;
}
function MYMODULE_MYFORM_add_item($form, &$form_state) {
// All we need is to increase the number used in our for loop above ...
$form_state['number_names']++;
// ... and rebuild our form.
$form_state['rebuild'] = TRUE;
}
function MYMODULE_MYFORM_remove_item($form, &$form_state) {
// Just the other way around until only one item is left ...
if ($form_state['number_names'] > 1) {
$form_state['number_names']--;
}
// ... and form rebuild again.
$form_state['rebuild'] = TRUE;
}
Drupal 8
Confira os módulos de exemplo AjaxAddMore.php
(clique no pequeno link "Visualizar fonte").