-1

I have two entity types -- video and video progress.

I've got a form on video nodes with a field that is populated with the id of a video progress entity that references the current node. If this field is empty when the form is submitted, then I am generating a new video progress entity in the submit handler, and am trying to populate my form field value with this new entity id. This form is hidden from the user and is updated dynamically as the user watches a video via jQuery.

My issue is that no matter what I try, I cannot get the submit or ajax callbacks to rebuild my field. Here are the relevant portions of my code.

function video_progress_tracking_form($form, &$form_state) {
  // $progress_id is already set

  $form['progress_id'] = array(
    '#type' => 'textfield',
    '#title' => t('Video progress entity id'),
    '#default_value' => $progress_id,
    '#element_validate' => array('element_validate_integer_positive'), 
  );

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit',
    '#ajax' => array(
      'callback' => 'video_progress_tracking_form_ajax_handler',
      'effect' => 'fade',
    ),
  );

  return $form;
}

function video_progress_tracking_form_submit($form, &$form_state){
  if(empty($form_state['progress_id'])) {
    // If a video progress entity doesn't exist, we need to create one
    $entity_type = 'video_progress';
    $entity = entity_create($entity_type, array('type' => 'video_progress'));
    $wrapper = entity_metadata_wrapper($entity_type, $entity);
    $wrapper->save();

    // Pass our new values into the form for further updating
    $form_state['values']['progress_id'] = $wrapper->id->value();  
  }
}

function video_progress_tracking_form_ajax_handler(&$form, &$form_state) {
  return $form['progress_id'];
}

I have also tried, among other things:

  • Setting a #value when initially building the form on $form['progress_id'] with a ternary operator so that if there is a form_state value for the field then that is set
  • Setting $form_state['rebuild'] = TRUE in both callbacks
  • Returning the entire form instead of just this single field

2 Answers 2

1

You haven't told the form API where to render the content you're returning in the AJAX callback.

That takes the form of a prefix/suffix on the element itself, with a predictable HTML ID:

$html_id = drupal_html_id('foo');
$form['progress_id'] = array(
  '#type' => 'textfield',
  '#title' => t('Video progress entity id'),
  '#default_value' => $progress_id,
  '#element_validate' => array('element_validate_integer_positive'), 
  '#prefix' => '<div id="' . $html_id . '">',
  '#suffix' => '</div>',
);

And providing the AJAX-ified element with the ID of the wrapping HTML:

$form['submit'] = array(
  '#type' => 'submit',
  '#value' => 'Submit',
  '#ajax' => array(
    'callback' => 'video_progress_tracking_form_ajax_handler',
    'effect' => 'fade',
    'wrapper' => $html_id,
  ),
);    

You will need to add/keep $form_state['rebuild'] = TRUE; in the submit handler (not the AJAX callback). To isolate that functionality you may wish to add a specific #submit handler array to your submit button.

4
  • Can you think of why it still wouldn't be working? I've added the prefix and suffix to my field, the wrapper to #ajax, and $form_state['rebuild'] = TRUE to the submit function, but the field is remaining empty after submit. I've verified that $form_state['values']['progress_id'] is set in my AJAX callback prior to return $form['progress_id'].
    – Mrweiner
    Commented Nov 2, 2017 at 20:41
  • It also doesn't seem to make a difference whether I designate $form_state['rebuild'] = TRUE in the default callback or within a secondary callback (if that matters).
    – Mrweiner
    Commented Nov 2, 2017 at 20:48
  • It might come down to where you're getting $progress_id from in the form builder. That should be coming from $form_state['values']['progress_id'] if it's set, is that what you've got? You have a small (unrelated) bug in the submit handler BTW, you should be testing $form_state['values']['progress_id'] rather than $form_state['progress_id'].
    – Clive
    Commented Nov 2, 2017 at 20:57
  • Ah, got it. I forgot to move some logic into an else condition so $progress_id was getting reset before it hit my field -- gah! Thanks! Good catch on the bug -- it's actually commented already on my end to make sure my entities were generated.
    – Mrweiner
    Commented Nov 2, 2017 at 21:27
1
$form['progress_id'] = array(
        '#type' => 'textfield',
        '#title' => t('Video progress entity id'),
        '#default_value' => $progress_id,
        '#element_validate' => array('element_validate_integer_positive'), 
      );
      $form['submit'] = array(
        '#type' => 'submit',
        '#value' => 'Submit',
        '#ajax' => array(
          'callback' => 'video_progress_tracking_form_ajax_handler',
          'effect' => 'fade',
        ),
      );

by

 $form['progress_id'] = array(
    '#prefix' => '<div id="my-div-ajax">',
    '#suffix' => '</div>',

    '#type' => 'textfield',
    '#title' => t('Video progress entity id'),
    '#default_value' => $progress_id,
    '#element_validate' => array('element_validate_integer_positive'), 
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit',
    '#ajax' => array(

      'callback' => 'video_progress_tracking_form_ajax_handler',
      'wrapper' => 'my-div-ajax',
      'effect' => 'fade',
    ),
  );

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.