feat(post-form): native datetime-local picker + require date client-side
The stock Grav `datetime` field template is deprecated and falls back to a plain text box, so `type: datetime` + `default: now` rendered a raw input showing the literal word "now" — unusable. Add a theme override at templates/forms/fields/datetime/datetime.html.twig that renders a native <input type="datetime-local"> (real calendar+clock, great on mobile), drop the `default: now`, and prefill the current local time from post-form.js. Also add `date` to the existing client-side validator. Together with the picker (which can't hold an invalid value) this stops a bad/empty date from round-tripping to the server — which was the trigger that made Grav re-render the managed FilePond field from the session flash as filename-only inputs and resurrect a photo the user had removed. Grav still reformats the submitted value to the blueprint `format: 'Y-m-d H:i'` on save, so stored dates and folder slugs are unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -46,8 +46,12 @@ form:
|
|||||||
-
|
-
|
||||||
name: date
|
name: date
|
||||||
label: Date & Time
|
label: Date & Time
|
||||||
|
# Rendered as a native <input type="datetime-local"> by the theme
|
||||||
|
# override at templates/forms/fields/datetime/datetime.html.twig.
|
||||||
|
# No `default: now` — the stock text fallback would print the literal
|
||||||
|
# string "now" into the picker; post-form.js prefills the current
|
||||||
|
# local time instead (and the client validator requires this field).
|
||||||
type: datetime
|
type: datetime
|
||||||
default: now
|
|
||||||
format: 'Y-m-d H:i'
|
format: 'Y-m-d H:i'
|
||||||
validate:
|
validate:
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -433,11 +433,29 @@ function initGeo() {
|
|||||||
* Replaces the template's inline validator. Reads the EasyMDE-synced content
|
* Replaces the template's inline validator. Reads the EasyMDE-synced content
|
||||||
* value (initEditor keeps the textarea current) and shows per-field messages.
|
* value (initEditor keeps the textarea current) and shows per-field messages.
|
||||||
*/
|
*/
|
||||||
|
// Current local wall-clock time as the value a datetime-local input expects
|
||||||
|
// ("YYYY-MM-DDTHH:MM"). Uses the browser's timezone — the server has no idea
|
||||||
|
// where the traveller is — and strips seconds so the value round-trips cleanly.
|
||||||
|
function localNowDatetime() {
|
||||||
|
var d = new Date();
|
||||||
|
d.setSeconds(0, 0);
|
||||||
|
d.setMinutes(d.getMinutes() - d.getTimezoneOffset());
|
||||||
|
return d.toISOString().slice(0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
function initValidation() {
|
function initValidation() {
|
||||||
var REQUIRED = { title: 'Title', content: 'Content' };
|
var REQUIRED = { title: 'Title', date: 'Date & time', content: 'Content' };
|
||||||
var form = document.querySelector('form[name="new-entry"]');
|
var form = document.querySelector('form[name="new-entry"]');
|
||||||
if (!form) return;
|
if (!form) return;
|
||||||
|
|
||||||
|
// Prefill the date/time picker with "now" (local) unless draft restore
|
||||||
|
// already put a value there. initDraft runs before initValidation in boot(),
|
||||||
|
// so an empty field here means there was no saved draft date to keep.
|
||||||
|
var dateEl = field('date');
|
||||||
|
if (dateEl && !String(dateEl.value).trim()) {
|
||||||
|
dateEl.value = localNowDatetime();
|
||||||
|
}
|
||||||
|
|
||||||
function clearErrors() {
|
function clearErrors() {
|
||||||
form.querySelectorAll('.field-error').forEach(function (el) { el.remove(); });
|
form.querySelectorAll('.field-error').forEach(function (el) { el.remove(); });
|
||||||
form.querySelectorAll('.field-invalid').forEach(function (el) { el.classList.remove('field-invalid'); });
|
form.querySelectorAll('.field-invalid').forEach(function (el) { el.classList.remove('field-invalid'); });
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{# intotheeast override of Grav's datetime field.
|
||||||
|
|
||||||
|
Grav's stock forms/fields/datetime/datetime.html.twig is DEPRECATED and just
|
||||||
|
extends the text field, so `type: datetime` renders a plain <input type="text">
|
||||||
|
— the owner sees a raw box (the literal word "now" from `default: now`) with no
|
||||||
|
way to pick a date/time. Here we render a native <input type="datetime-local">
|
||||||
|
instead: a real calendar + clock picker, and an excellent one on mobile.
|
||||||
|
|
||||||
|
The value is prefilled to the current local time by post-form.js (JS knows the
|
||||||
|
traveller's timezone; the server doesn't), and the existing client-side
|
||||||
|
validator now requires this field — so an empty or invalid date can no longer
|
||||||
|
reach the server and destroy the FilePond photo list on a re-render. #}
|
||||||
|
{% extends "forms/field.html.twig" %}
|
||||||
|
|
||||||
|
{% block input_attributes %}
|
||||||
|
type="datetime-local"
|
||||||
|
{{ parent() }}
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user