0

I have a modal form that I added to my module and patterned it after this article.

I have used it before with no issues, I was able to use the method to show the form and then save the data.

Now I am populating the form as an edit form. When I submit the form it calls the controller again, which calls the buildForm() method of the modal class and then wipes out the data that was entered into the form. The data was in the $form_state correct but after the buildForm() runs it finally get to the AJAX call back handler and the data is no longer in the $form_state. It is totally gone. I am not sure how to solve this. I can't update anything in Drupal based on the form submit.

TimeOffApprovalController.php (Entry point of the route)

namespace Drupal\timeoff\Controller;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\OpenModalDialogCommand;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Form\FormBuilder;

class TimeOffApprovalController extends ControllerBase {

  /**
   * The form builder.
   *
   * @var \Drupal\Core\Form\FormBuilder
   */
  protected $formBuilder;

  /**
   * The ModalFormExampleController constructor.
   *
   * @param \Drupal\Core\Form\FormBuilder $formBuilder
   *   The form builder.
   */
  public function __construct(FormBuilder $formBuilder) {
    $this->formBuilder = $formBuilder;
  }

  /**
   * {@inheritdoc}
   *
   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
   *   The Drupal service container.
   *
   * @return static
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('form_builder')
    );
  }

  /**
   * Callback for opening the modal form.
   */
  public function openModalForm($id) {
    $response = new AjaxResponse();

    // Get the modal form using the form builder.
    $modal_form = $this->formBuilder->getForm('Drupal\timeoff\Form\TimeOffApprovalForm', $id);

    // Add an AJAX command to open a modal dialog with the form as the content.
    $response->addCommand(new OpenModalDialogCommand('Approval Form', $modal_form, ['width' => '800']));

    return $response;
  }

}

TimeOffApprovalForm.php (Modal form)

namespace Drupal\timeoff\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\OpenModalDialogCommand;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\timeoff\Controller\TimeOffController;
use Drupal\Core\Ajax\RedirectCommand;

class TimeOffApprovalForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'modal_form_example_modal_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, $options = NULL) {
    $form['#prefix'] = '<div id="modal_example_form">';
    $form['#suffix'] = '</div>';

    // The status messages that will contain any form errors.
    $form['status_messages'] = [
      '#type' => 'status_messages',
      '#weight' => -10,
    ];

    $ids = \Drupal::entityQuery('time_off_day')
                  ->condition('timeoffid', $options)
                  ->execute();
    $entitys = \Drupal::entityTypeManager()->getStorage('time_off_day')->loadMultiple($ids);

    $deny_dropdown = array();
    $hours_value = array();

    foreach ($entitys as $the_entity) {
      $deny_dropdown[$the_entity->id()] = t($the_entity->label());
      $hours_value[$the_entity->id()] = $the_entity->getTimeOffHours();
      $form[$the_entity->getTimeOffDate()] = array(
        '#type' => 'textfield',
        '#title' => t($the_entity->getTimeOffDate()),
        '#value' => t($the_entity->getTimeOffHours()),
        '#required' => TRUE,
      );
    }

    $form['timeoffid'] = array(
      '#type' => 'hidden',
      '#value' => $options,
    );
    $form['actions'] = array('#type' => 'actions');
    $form['actions']['send'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit Approval form'),
      '#attributes' => [
        'class' => [
          'use-ajax',
        ],
      ],
      '#ajax' => [
        'callback' => [$this, 'submitApprovalFormAjax'],
        'event' => 'click',
      ],
    ];

    $form['#attached']['library'][] = 'core/drupal.dialog.ajax';

    return $form;
  }

  /**
   * AJAX callback handler that displays any errors or a success message.
   */
  public function submitApprovalFormAjax(array $form, FormStateInterface $form_state) {
    $response = new AjaxResponse();

    // If there are any form errors, re-display the form.
    if ($form_state->hasAnyErrors()) {
      $response->addCommand(new ReplaceCommand('#modal_example_form', $form));
    }
    else {

      // Do the time off denial
      //$id = $form_state->getValue('timeoffid');
      //$denialid = $form_state->getValue('deny_reason');
      //$comment = $form_state->getValue('deny_comment');
      //$timeoffcontroller = new TimeOffController();
      //$timeoffcontroller->deny($id, $denialid, $comment);

      $referer_url = $_SERVER['HTTP_REFERER'];
      $response->addCommand(new RedirectCommand($referer_url));
    }

    foreach ($form_state->getValues() as $key => $value) {
      drupal_set_message($key . ': ' . $value);
    }

    return $response;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {}

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {}

  /**
   * Gets the configuration names that will be editable.
   *
   * @return array
   *   An array of configuration object names that are editable if called in
   *   conjunction with the trait's config() method.
   */
  protected function getEditableConfigNames() {
    return ['config.modal_form_example_modal_form'];
  }
}

Any help?

  • I am doing some more testing and have determined that the values array for the form_state is not being populated with any data. I do see the date in the _POST. I am not sure why it is not placing the submitted data in the values array. – Robert Fulcher Nov 16 '18 at 16:52
  • Try populating the form fields with #default_value =>.... instead of #value – theuni Nov 17 '18 at 18:48
  • @theuni - That worked great. How do I give you credit for that? I can't believe I did not pick that up. I feel like sometimes you can reet 100 pages and not see something. – Robert Fulcher Nov 18 '18 at 2:47
  • Good it's working now! If you want you can upvote my comment – theuni Nov 18 '18 at 17:00
1

Populating a form field should be done via '#default_value' => ... instead of '#value' => ...

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.