Shopify / twine

Twine is a minimalistic two-way binding system
MIT License
115 stars 11 forks source link

Radios: Impossible to use DOM API to update checked value and get Twine in sync #92

Open qq99 opened 7 years ago

qq99 commented 7 years ago

Consider this codepen @ http://codepen.io/qq99/pen/wgBBzL?editors=1010#0

2 radios, both bound to some Twine variable, and you want to, from somewhere else, say radioEl.checked = true. However, Twine will not update state properly, even if you call Twine.refresh() after setting this.

Ideally, the API for such a thing would look like either:

  1. radioEl.checked = true; and Twine reflects that state, but this would probably require https://developer.mozilla.org/en/docs/Web/API/MutationObserver (if that's the correct thing)
  2. radioEl.checked = true; Twine.refresh() is more inline with workarounds we do today when bypassing Twine, but it doesn't work for this usecase

The only workaround today is:

radioEl.checked = true
$(radioEl).trigger('change')

cc @Shopify/tnt

pushrax commented 7 years ago

Twine.refresh is designed to only output to the DOM, not read from it. The idea is that you change the JS variable rather than the element.

I assume you're asking this because of a 3rd-party library that is mutating the DOM without emitting events. What you need is for the change handler to be called. It would be possible to make a function that does this for all Twine-tracked elements but it would be rather slow I imagine. How necessary is this?

qq99 commented 7 years ago

That's fair @pushrax

In this case, it was our own code mutating DOM via radioEl.checked = true, not a 3rd party lib. I think it was an attempt to implement a delegated bind-event-click on a parent of many radios (bubbles up to container, code finds specific radio in child, tries to turn it on). I guess the bug wasn't seen because it looked visually checked, but Twine didn't reflect it.

I can imagine other scenarios where 3rd party libs would do such things though. I also imagine there must be at least one other spot in our JS hoping to do something similar (maybe we can search for .value = and .checked =)

How necessary is this?

not sure tbh, I think it's low in priority but I figured I'd log it with the codepen for posterity. To be able to use DOM API directly and have Twine minimally just work is more of an "in the ideal world" thing for me. Depends I guess on the future evolution of our JS FED system and Twine in general.

Rather than make a custom function for it, would mutation observers work? I guess the downside is browser support for those