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

Allow MutationObserver to observe (certain) element property changes #1340

Open
bramus opened this issue Nov 26, 2024 · 4 comments
Open

Allow MutationObserver to observe (certain) element property changes #1340

bramus opened this issue Nov 26, 2024 · 4 comments
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest

Comments

@bramus
Copy link

bramus commented Nov 26, 2024

What problem are you trying to solve?

Some elements have an internal state that can change. Think of a checkbox whose checked property gets updated as you check/uncheck this.

This type of change is not observable by MutationObserver because this mutation is not reflected in the DOM tree: it’s only the property that gets updated, not the attribute.

I would love to be able to respond to this type of change with a MutationObserver because of the timing of the MutationObserver callback: it’s a microtask. This allows me to respond to a change before any of the rendering steps are executed.

In my use-case specifically, I’d use this to automatically trigger View Transitions. Other use-cases could be to do something like form field validation.

What solutions exist today?

Workarounds include listening for specific events on those elements. For input for example this is the click event (and not change because that fires too late), which you can hijack to be able to respond to it. This is cumbersome to implement as not all browsers/platforms respond in the same way, and not all elements/properties can use the same event.

Some other hacks/workarounds such as responding to a selector match changing exist (see here) but these rely on going round the event loop once. Because of that, the code to respond to a DOM property mutation fires after a frame already got rendered, which is too late for this use-case.

Other workarounds suggest to override the getter and setter which is not something that I would not recommend + it also doesn’t work with the property being changed not by code (as in: you actually clicking it).

How would you solve it?

A new boolean in the MutationObserverInit dictionary to enable/disable monitoring DOM properties.

Maybe, for performance reasons, instead of a boolean this could be an array of strings resembling the properties that the author wants to monitor – like attributeFilter.

Additionally, the list of observable properties could be limited to a predefined list that only reflect the element’s state. For all inputs that would be value, for checkboxes/radio buttons that would be checked, for select elements selectedIndex, etc. This would make the feature less of a performance footgun when used.

Anything else?

An alternative approach could be to reflect changes to a state (such as a checkbox getting checked) in the markup, by actually updating the attribute synchronously as well so that an (unmodified) MutationObserver can respond to the change.

For text inputs specifically this synchronization could be enforced trough the proposed beforechange event (see whatwg/html#10639). Ideally, it would have a more generic solution that can cater for many more properties and types of elements.

@bramus bramus added addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest labels Nov 26, 2024
@annevk
Copy link
Member

annevk commented Nov 26, 2024

This is cumbersome to implement as not all browsers/platforms respond in the same way

That seems like a bug that needs to be fixed. No reason to expect a new API is going to make this better.

Also, there's no way to "just" make this work for arbitrary properties. That'd require patching every object. Making sure events fire consistently seems like a much better fix.


Also: https://esdiscuss.org/topic/an-update-on-object-observe.

@bramus
Copy link
Author

bramus commented Dec 3, 2024

This is cumbersome to implement as not all browsers/platforms respond in the same way

That seems like a bug that needs to be fixed. No reason to expect a new API is going to make this better.

My main point of focus in this sentence is that it’s cumbersome to implement. If there are inconsistencies (which I still need to check) across browsers but also across platforms then those indeed need to be fixed.

Cumbersome workarounds include:

Also, there's no way to "just" make this work for arbitrary properties. That'd require patching every object.

In my proposal I suggest at limiting this to only a handful of properties, namely those that reflect the primary state of the component – e.g. a checkbox being checked or not. This limited list of properties could be marked as “observable” which causes changes to it to be wired into MutationObserver.

Making sure events fire consistently seems like a much better fix.

Problem is that these events fire too late. To work properly, the code that I want to execute in response to a change needs to fire before rendering … which led me to MutationObserver.

Also: https://esdiscuss.org/topic/an-update-on-object-observe.

Is there a specific post you want me to read from that thread? If it’s the one about using a Proxy then I can say it won’t work. Yes, you can Proxy around getting/setting the checked property of a checkbox, but that only triggers when setting it programmatically, not when it gets set by actually clicking the checkbox.

@bramus
Copy link
Author

bramus commented Dec 10, 2024

(Just noticed this issue should have been posted in whatwg/dom instead of whatwg/html. @annevk: can you move this issue?)

@zcorpan zcorpan transferred this issue from whatwg/html Dec 16, 2024
@zcorpan
Copy link
Member

zcorpan commented Dec 16, 2024

I've moved this to whatwg/dom

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

3 participants