Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

matchMedia-like API for element matches #1225

Open
matthewp opened this issue Sep 10, 2023 · 0 comments
Open

matchMedia-like API for element matches #1225

matthewp opened this issue Sep 10, 2023 · 0 comments
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest

Comments

@matthewp
Copy link

It would be useful to receive an event when an element's matches(selector) changes, similar to how you can do so with matchMedia.

The ability to reactively change styles based on selector changes in CSS is a powerful feature we do not have in the DOM. Instead to achieve similar reactivity we need to account for the variety of ways in which state may change that includes things like:

  • User events
  • Network events (fetch(), web sockets, SSE)
  • Cross-frame / cross-window message events

And probably a lot more.

Use-case

You want to mark a submit button as disabled when the form is invalid. You might naively write this code:

const form = document.querySelector('form');
const submit = document.querySelector('input[type=submit]');

submit.disabled = form.matches(':invalid');

const checkValid = () => {
  submit.disabled = form.matches(':invalid');
};

form.addEventListener('input', checkValid);

This works pretty well, but if the requirements change and say you do something like:

  • Clear an input if server-side validation fails via an asynchronous fetch request.
  • Clear an input if the form times out (5 minute timeout).

These things will not trigger an input so the submit button might be incorrectly enabled. Here's an example codepen that demonstrates this problem: https://codepen.io/matthewp/pen/MWZpBYd

Proposal 1

This is inspired by matchMedia, Element.prototype.match:

const query = form.match(':invalid');

submit.disabled = query.matches;
query.addEventListener('change', () => {
  submit.disabled = query.matches;
});

Proposal 2

I prefer proposal 1, but there might be issues with it and I'm not sure if this style API is still in style. I defer to the experts here. My second proposal would follow the observer pattern:

const observer = new QueryObserver((entries) => {
  form.disabled = entries.at(-1).matches;
});

observer.observe(form, ':invalid');
@annevk annevk added needs implementer interest Moving the issue forward requires implementers to express interest addition/proposal New features or enhancements labels Sep 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest
Development

No branches or pull requests

2 participants