0

I have a form which defines a datetime field as follows:

   $form['register'][$i]['end_date_time'] = [
      '#type' => 'datetime',
      '#default_value' => new DrupalDateTime($data->field_event_time_end_value, 'Europe/London'),
      '#date_date_element' => 'text',
      '#date_date_format' => 'd/m/Y',
      '#date_time_element' => 'text',
      '#date_time_format' => 'H:i:s',
      '#date_timezone' => 'Europe/London',
      '#weight' => '0',
    ];

However whenever I try to submit the form every date field throws a validation error stating "The date is invalid. Please enter a date in the format 26/07/2019 16:47:43". I don't have any logic in my validateForm(array &$form, FormStateInterface $form_state) function yet so I am not sure why it is throwing an error.

I have tried different combinations of formatting the date and even stripped it back to the basic settings but I can't get a combination to work. I am currently on Drupal 8.7.5.


Update to include my full form code:

<?php

namespace Drupal\events_register\Form;

use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Database\Driver\mysql\Connection;
use Drupal\Core\Messenger\MessengerInterface;

/**
 * Class EventRegisterForm.
 */
class EventRegisterForm extends FormBase {

  /**
   * Drupal\Core\Database\Driver\mysql\Connection definition.
   *
   * @var \Drupal\Core\Database\Driver\mysql\Connection
   */
  protected $database;

  /**
   * Drupal\Core\Messenger\MessengerInterface definition.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * The webform storage.
   *
   * @var \Drupal\webform\WebformEntityStorageInterface
   */
  protected $webformStorage;

  /**
   * The webform submission storage.
   *
   * @var \Drupal\webform\WebformSubmissionStorageInterface
   */
  protected $webformSubmissionStorage;

  /**
   * Webform request handler.
   *
   * @var \Drupal\webform\WebformRequestInterface
   */
  protected $requestHandler;

  /**
   * Constructs a new EventRegisterForm object.
   *
   * @param \Drupal\Core\Database\Driver\mysql\Connection $database
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function __construct(Connection $database, MessengerInterface $messenger,  EntityTypeManagerInterface $entity_type_manager) {
    $this->database = $database;
    $this->messenger = $messenger;
    $this->webformStorage = $entity_type_manager->getStorage('webform');
    $this->webformSubmissionStorage = $entity_type_manager->getStorage('webform_submission');
    $this->requestHandler = $request_handler;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('database'),
      $container->get('messenger'),
      $container->get('entity_type.manager')
    );
  }

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

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    //kint($this->webformSubmissionStorage->load(1));
    $form['register'] = [
      '#type' => 'table',
      '#caption' => t('Sample Table'),
      '#header' => [
        'nid' =>    t('Node ID'),
        'n_title' =>    t('Title'),
        'n_start_date' =>    t('Start Date'),
        'n_end_date' =>    t('End Date'),
        'sid' => t('Submission ID'),
        'student_id' => t('Student ID'),
        'registration_status' => t('Registration Status'),
      ],
      '#empty' => t('Nothing found'),
    ];
    // Get records from the DB.
    $query = $this->database->select('webform_submission', 'ws');
    $query->fields('ws', ['sid','webform_id']);
    $query->join('node_field_data', 'nfd', 'ws.entity_id = nfd.nid');
    $query->fields('nfd', ['nid', 'title', 'uid']);
    $query->join('node__field_event_time', 'nfet', 'nfd.nid = nfet.entity_id');
    $query->fields('nfet', ['field_event_time_value', 'field_event_time_end_value']);
    $query->leftJoin('node__field_event_tutor', 'nfetu', 'nfd.nid = nfetu.entity_id');
    $query->fields('nfetu', ['field_event_tutor_target_id']);
    $pager = $query->extend('Drupal\Core\Database\Query\PagerSelectExtender')->limit(10);
    $results = $pager->execute()->fetchAll();
    if ($results) {
      $i = 0;
      foreach ($results as $data) {
        $form['register'][$i]['node_id'] = [
          '#type' => 'item',
          '#markup' => $data->nid,
          '#weight' => '0',
        ];
        $form['register'][$i]['title'] = [
          '#type' => 'item',
          '#markup' => $data->title,
          '#weight' => '0',
        ];

        $form['register'][$i]['start_date_time'] = [
          '#type' => 'datetime',
          '#default_value' => new DrupalDateTime($data->field_event_time_value, 'Europe/London'),
          '#date_date_element' => 'date',
          '#date_date_format' => 'd/m/Y',
          '#date_time_element' => 'time',
          '#date_time_format' => 'H:i:s',
          '#date_timezone' => 'Europe/London',
          '#weight' => '0',
        ];
        $form['register'][$i]['end_date_time'] = [
          '#type' => 'datetime',
          '#default_value' => new DrupalDateTime($data->field_event_time_end_value, 'Europe/London'),
          '#date_date_element' => 'date',
          '#date_date_format' => 'd/m/Y',
          '#date_time_element' => 'time',
          '#date_time_format' => 'H:i:s',
          '#date_timezone' => 'Europe/London',
          '#weight' => '0',
        ];
        $form['register'][$i]['submission_id'] = [
          '#type' => 'item',
          '#markup' => $data->sid,
          '#weight' => '0',
        ];
        $submissionData = $this->webformSubmissionStorage->load($data->sid);
        $form['register'][$i]['student_id'] = [
          '#type' => 'item',
          '#markup' => $submissionData->getData()["student_id"],
          '#weight' => '0',
        ];
        $form['register'][$i]['student_id'] = [
          '#type' => 'item',
          '#markup' => $submissionData->getData()["student_id"],
          '#weight' => '0',
        ];
        $status_options = ['attending' => 'attending', 'attended' => 'attended', 'cancelled' => 'cancelled', 'system_cancellation' => 'system cancellation'];
        $form['register'][$i]['status'] = [
          '#type' => 'select',
          '#options' => $status_options,
          '#default_value' => $submissionData->getData()["registration_status"],
          '#weight' => 0,
        ];
        $i++;
      }
    }
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    ];
    $form['pager'] = array(
      '#type' => 'pager',
    );
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    foreach ($form_state->getValues() as $key => $value) {
      \Drupal::messenger()->addMessage($key . ': ' . ($key === 'text_format'?$value['value']:$value));
    }
    parent::validateForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // Display result.
    foreach ($form_state->getValues() as $key => $value) {
      \Drupal::messenger()->addMessage($key . ': ' . ($key === 'text_format'?$value['value']:$value));
    }
  }
}

2 Answers 2

0

Try changing. #date_date_element => 'date' type to date instead of text. And #date_time_element => 'time' type to time instead of text.


UPDATE

This code works just fine for me on Drupal 8.7.5:

for($i = 0; $i < 5; $i++){
  $form['test'][$i]['end_date_time'] = [
    '#type' => 'datetime',
    '#default_value' => DrupalDateTime::createFromTimestamp(time()),
    '#date_date_element' => 'date',
    '#date_date_format' => 'd/m/Y',
    '#date_time_element' => 'time',
    '#date_time_format' => 'H:i:s',
    '#date_timezone' => 'Europe/London',
    '#weight' => '0',
  ];
}

You might want to check the value of the $data->field_event_time_end_value field.
Also, check the DrupalDateTime.php docs for how to create a proper instance.

3
  • Unfortunately that does not work for my form. I still get the error message: The date is invalid. Please enter a date in the format 2019-07-27 18:27:23.
    – inertiahz
    Jul 27, 2019 at 17:30
  • @inertiahz I updated my answer. Maybe you should share more of the code you're using right now. Jul 28, 2019 at 12:00
  • Thank you for updating your answer - unfortunately that still doesn't work for me. I have a feeling I may be doing something else wrong and that the above code should work as I can see examples of it throughout the Drupal codebase. I've updated my question to include the full form class, in case anyone can spot anything else that might be causing the conflict.
    – inertiahz
    Jul 28, 2019 at 13:24
0

It's because the datetime elements are inside a table element.

There's a dead issue here: #3016258: Datetime and Datelist form elements are never validate when put in a table element (linking to a more general issue, that I suspect will eventually fix this: #3247373: Form API Table element is being treated as an input element, this can break fields that have a handler defined which are now no longer altering the data in the $form_state array.).

There is 2 work arounds in issue #3247373, settings the #input to FALSE for your table should work in your use case:

$form['register'] = [
  '#type' => 'table',
  '#caption' => t('Sample Table'),
  '#header' => [
    'nid' =>    t('Node ID'),
    'n_title' =>    t('Title'),
    'n_start_date' =>    t('Start Date'),
    'n_end_date' =>    t('End Date'),
    'sid' => t('Submission ID'),
    'student_id' => t('Student ID'),
    'registration_status' => t('Registration Status'),
  ],
  '#empty' => t('Nothing found'),
  '#input' => FALSE
];

Do note this a workaround, and it might have other consequences, I've used the workaround before without any complications.

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.