Use MutationObserver to constrain dynamically-rendered date inputs
Previous afterNavigate hook missed inputs inside conditional blocks that appear after user interaction (e.g. the "+ New Expense" form). Replaced with a MutationObserver on document.body that catches every <input type="date"> as it's added to the DOM and sets min/max. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,23 +1,34 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import '../app.css';
|
import '../app.css';
|
||||||
import { afterNavigate } from '$app/navigation';
|
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
let { children } = $props();
|
let { children } = $props();
|
||||||
|
|
||||||
// Constrain date inputs so browsers don't render yyyyyy-mm-dd
|
// Constrain date inputs so browsers don't render yyyyyy-mm-dd.
|
||||||
function constrainDateInputs() {
|
// Uses a MutationObserver so dynamically-rendered inputs get constrained too.
|
||||||
document.querySelectorAll<HTMLInputElement>('input[type="date"]').forEach((el) => {
|
function constrainEl(el: Element) {
|
||||||
|
if (!(el instanceof HTMLInputElement)) return;
|
||||||
|
if (el.type !== 'date') return;
|
||||||
if (!el.hasAttribute('min')) el.setAttribute('min', '1900-01-01');
|
if (!el.hasAttribute('min')) el.setAttribute('min', '1900-01-01');
|
||||||
if (!el.hasAttribute('max')) el.setAttribute('max', '2100-12-31');
|
if (!el.hasAttribute('max')) el.setAttribute('max', '2100-12-31');
|
||||||
});
|
}
|
||||||
|
function constrainRoot(root: ParentNode) {
|
||||||
|
root.querySelectorAll<HTMLInputElement>('input[type="date"]').forEach(constrainEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
constrainDateInputs();
|
constrainRoot(document);
|
||||||
|
const observer = new MutationObserver((mutations) => {
|
||||||
|
for (const m of mutations) {
|
||||||
|
for (const node of m.addedNodes) {
|
||||||
|
if (node.nodeType !== 1) continue;
|
||||||
|
constrainEl(node as Element);
|
||||||
|
if ((node as Element).querySelectorAll) constrainRoot(node as Element);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
afterNavigate(() => {
|
observer.observe(document.body, { childList: true, subtree: true });
|
||||||
queueMicrotask(constrainDateInputs);
|
return () => observer.disconnect();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user