1

Hi I'm a newbie to drupal and I'm practicing using drupal 7 forms #ajax.

I have 2 fieldsets the ingredient fieldset and the steps fieldset.

when I click add step it works fine but when I click add ingredient and remove a step from the step fieldset the step fieldset turns into ingredient field set

enter image description here

here's my form and functions

function recipe_new_recipe($form, &$form_state) {
$form = array();

$form['#tree'] = TRUE;

// Fieldset for details of recipe
$form['details_fieldset'] = array(
    '#type' => 'fieldset',
    '#title' => t('Recipe Details'),
);

$form['details_fieldset']['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Recipe name'),
    '#description' => t('Name of the recipe'),
);

$form['details_fieldset']['description'] = array(
    '#type' => 'textarea',
    '#title' => t('Description'),
    '#description' => t('Recipe description'),
    '#resizable' => FALSE,
);

$form['details_fieldset']['time'] = array(
    '#type' => 'textfield',
    '#size' => 10,
    '#title' => t('Preparation time'),
    '#description' => t('Recipe preparation time'),
);

$form['details_fieldset']['serving_size'] = array(
    '#type' => 'textfield',
    '#size' => 8,
    '#title' => t('Serving size'),
    '#description' => t('Recipe serving size'),
);

// Initialization of variables for ingredients
if(empty($form_state['ingredient_num'])) {
    // ingredient number f
    $form_state['ingredient_num'] = 1;
    // ingredient checker array stores all removed  ingredients
    $form_state['ingredient_check'] = array ();
    $form_state['ingredient_count'] = 1;
    $form_state['ingredient_check'][$form_state['ingredient_num']] = 1;
}
// Fieldset for ingredients
$form['ingredient_fieldset'] = array(
    '#type' => 'fieldset',
    '#title' => t('Recipe ingredients'),
    '#prefix' => '<div id="recipe_ingredients">',
    '#suffix' => '</div>',

);
//For loop for dynamic fields for ingredients
for ($i=1; $i <= $form_state['ingredient_num']; $i++) {
    // check array = 1 render the field ( for rendering field in the bottom only )
    if($form_state['ingredient_check'][$i] == 1){
        $form['ingredient_fieldset']['ingredient'][$i]['field'] = array(
        '#type' => 'textfield',
        '#prefix' => '<div id = "ingredient_'. $i . '">',
        );

        if ($form_state['ingredient_count'] != 1) {
            $form['ingredient_fieldset']['ingredient'][$i]['remove_ingredient'] = array(
              '#type' => 'submit',
              '#value' => t('Remove'),
              '#submit' => array('remove_ingredient_list'), // function submit callback for removing ingredients
              '#suffix' => '</div>',
              '#name' => $i,
              '#ajax' => array(
                'callback' => 'ajax_remove_ingredient', // ajax callback function for removing ingredients
                'wrapper' => 'recipe_ingredients',
              ),
            );
        }
    }

}
// Add new ingredients button 
$form['ingredient_fieldset']['add_ingredient'] = array(
    '#type' => 'submit',
    '#value' => t('add another ingredient'),
    '#submit' => array('add_ingredient_list'), // function submit callback for adding ingredients
            '#ajax' => array(
        'callback' => 'ajax_add_ingredient', // ajax callback function for adding ingredients
        'wrapper' => 'recipe_ingredients'
    ),
);
// Fieldset steps
$form['step_fieldset'] = array(
    '#type' => 'fieldset',
    '#title' => t('Recipe steps'),
    '#prefix' => '<div id="recipe_steps">',
    '#suffix' => '</div>',

);
// Step variables initialization
if(empty($form_state['step_num'])) {
    $form_state['step_num'] = 1;
    $form_state['step_check'] = array ();
    $form_state['step_count'] = 1;
    $form_state['step_check'][$form_state['step_num']] = 1;
}
//For loop for dynamic fields for steps
for ($j=1 ; $j <= $form_state['step_num']; $j++) { 

    if($form_state['step_check'][$j] == 1){
        // check array = 1 render the field ( for rendering field in the bottom only )
        $form['step_fieldset']['step'][$j]['field'] = array(
        '#type' => 'textfield',
        '#prefix' => '<div id = "step'. $j . '">',
        );


        if($form_state['step_count'] != 1){
            $form['step_fieldset']['step'][$j]['remove_step'] = array(
              '#type' => 'submit',
              '#value' => t('Remove'),
              '#submit' => array('remove_step_list'), // function submit callback for removing steps
              '#suffix' => '</div>',
              '#name' => $j,
              '#ajax' => array(
                'callback' => 'remove_step', // ajax callback function for removing steps
                'wrapper' => 'recipe_steps' ,
              ),
            );
        }
    }

}
// Add new steps button 
$form['step_fieldset']['add_step'] = array(
    '#type' => 'submit',
    '#value' => t('add another step'),
    '#submit' => array('add_step_list'),
            '#ajax' => array(
        'callback' => 'add_step',
        'wrapper' => 'recipe_steps',
    ),
);

$form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit recipe'),
);

return $form; 
}

function add_ingredient_list($form, &$form_state){
$form_state['ingredient_num']++;
$check = $form_state['ingredient_num'];
$form_state['ingredient_count']++;
$form_state['ingredient_check'][$check] = 1;
$form_state['rebuild'] = TRUE;
}

function remove_ingredient_list($form, &$form_state) {
$key = $form_state['triggering_element']['#name'];
$form_state['ingredient_count']--;
$form_state['ingredient_check'][$key] = 2;
$form['ingredient_fieldset']['ingredient'][$key]['field']['#access'] =    FALSE;
$form['ingredient_fieldset']['ingredient'][$key]['remove_name']['#access'] = FALSE;
$form_state['rebuild'] = TRUE;
}
function ajax_add_ingredient($form, $form_state) {
return $form['ingredient_fieldset'];
}
function ajax_remove_ingredient($form, $form_state) {
return $form['ingredient_fieldset'];
}
function add_step_list($form, &$form_state){
$form_state['step_num']++;
$check = $form_state['step_num'];
$form_state['step_count']++;
$form_state['step_check'][$check] = 1;
$form_state['rebuild'] = TRUE;
}
function remove_step_list($form, &$form_state) {
$key = $form_state['triggering_element']['#name'];
$form_state['step_count']--;
$form_state['step_check'][$key] = 2;
$form['step_fieldset']['step'][$key]['field']['#access'] = FALSE;
$form['step_fieldset']['step'][$key]['remove_name']['#access'] = FALSE;
$form_state['rebuild'] = TRUE;
}
function add_step($form, $form_state) {
return $form['step_fieldset'];
}
function remove_step($form, $form_state) {
return $form['step_fieldset'];
}
1

I had the same issue recently, as it turns out it was calling the wrong callback because you need to have a unique '#name' for each of the buttons.

In your code you have the '#name' as $i and $j which represents a number but this means that the '#name' is not unique as both $i and $j can have the same number.

So for example, this:

'#name' => $i,

Should be something like:

'#name' => 'remove_ingredient_' . $i,

This differentiates the two so the right callback is used.

You then need to strip the text out of the '#name' to use the key:

function remove_ingredient_list($form, &$form_state) {
  $key = $form_state['triggering_element']['#name'];
  $key = str_replace('remove_ingredient_', '', $key);
  $form_state['ingredient_count']--;
  $form_state['ingredient_check'][$key] = 2;

I realise this is an old question but hopefully it helps anyone else having the same issue :-)

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.