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
Set non primitives as properties instead of attribute #2337
Conversation
As discussed on Gitter, it's rarely Mithril's place to make these assumptions about whether input should map to property or attribute (or both). Eg The classic case of near-enough bi-di binding is writable boolean attributes where
When this is desirable it is handled by the element's DOM as determined natively or in a custom element definition. There's a few special cases where Mithril does need to step in to determine how to handle special property / attribute handling - Current behaviour - assuming property setting by default - is correct. Native elements do (and custom elements can) use property setter traps to determine attribute mapping where desirable. In other scenarios - |
Sorry, but I think you might be thinking of the |
Haha sorry |
Sorry, I'm confused - I didn't realise we had a fall through to |
@porsager @barneycarroll The current behavior of attempting to set properties then falling through to setting attributes if missing been the behavior since the v0.2.x days. I'm heavily against this particular PR, though, specifically because it makes significant decisions based on the type of attributes' values. The only precedent we have for this is diffing How about this alternative: let's add two magic properties for DOM vnodes, |
Sorry, I'm very confused now too. I think this whole PR got muddled in I was actually sure we already decided to have this implemented in the issue i linked above, and that it was also implemented in the PR #2221 by you isiah, but that you either missed the crucial part or that there had been a regression since. |
I am also not understanding the arguments against this PR. Like @porsager says I can't think of any scenario where The MDN docs for
Emphasis is mine. @isiahmeadows I think in that link you posted the Are you suggesting that for custom elements to be compatible with Mithril they will have to override |
@isiahmeadows The nested attrs and props seem reasonable, but it does feel a bit awkward / non-standard. Would caching the Also I assume that these magic properties would be optional and existing attributes at the top level would continue to work as they do now? |
TL;DR: I wasn't reading current source correctly — but it is correct and the PR is unnecessary. I think I've muddied the water horribly, I apologise. I was wrong-footed by brain-farting some of my JavaScript interpretation & weird behaviour specifically relating to @isiahmeadows I think you had it right in 2220 when you said
@fuzetsu is IMO correct in asserting that A-frame's behaviour is exceptionally weird. Per MDN,
Attributes should be serialiseable, eg parsable as static XML and interpretable by CSS selectors. Back to @porsager's PR, what I was previously missing in the Mithril logical tree was the early condition to test for The reason your test cases aren't valid @porsager is that you're using plain elements while asserting that they could be custom elements with special interfaces for those non-standard properties: in practice any custom elements that did have special interfaces for those properties would expose them in the |
@barneycarroll True, and maybe we could |
Yeah, I misread the whole thing - I thought this was related to that when it wasn't. Apologies about that @porsager. (This quotes @porsager's comment, but it's really in reply to some of the subsequent discussion.)
We decided to keep Mithril's existing property + attribute fallback in place, to do to custom elements what's already done with DOM nodes. #2221 specifically says this in the description (emphasis not in original):
This is also documented here, where it states "And yes, this translates to both attributes and properties, and it works just like they would in the DOM." (Note to self for later: the docs in that section could stand to be revised to be a little less editorial-y around custom element support. For example: "[...] For example, you can use A-Frame within Mithril, no problem!" should read more like "[...] For example, you can use A-Frame with Mithril like this:". There's a couple other places that need some minor tweaks.) In addition, the existing behavior of passing properties through unmodified is documented in that same section: "For custom elements, it doesn't auto-stringify properties, in case they are objects, numbers, or some other non-string value". So yes, this is a breaking change which requires a docs update. But that particular section talks about passing through values only in reference to properties, leaving attributes purely implied, so unconditionally stringifying attributes is still something I'm open to. It also wouldn't be that hard, and I might be able to simplify a few HTML-specific checks. The key here is that custom elements are treated like normal HTML elements, just ones that happen to not need all the hacks. That's our story - custom elements are first-class elements, no extra support required. |
The implementation is still not quite complete, though: if you register your custom elements after Mithril sees it, it borks our data model. It is possible to fix, so it's not like we couldn't provide a better story. Oddly, this isn't tested for by the Custom Elements Everywhere site, so we might be a step ahead of our peers on it. |
@isiahmeadows I don't think forcibly coercing attribute values to string on Mithril's side is valuable. The behaviour happens automatically via the element interface, or in the case of A-frame, is skipped altogether. The definition promise is interesting. Presumably we'd want to then trigger a redraw that invalidates the previous vtree so a new one can be built from scratch with the right inferences? |
FWIW, my original intent is what's implied now. Like I said, I'm open to changing it, but I'm waiting for a compelling reason, and I'm just not seeing anything here persuasive enough to make the change.
Sure, but I'd also like a magic I'll file a new issue for this, since it's off-topic here. Edit: #2339 |
Wouldn't it make sense to dispatch once per element into either More generally, we could add a flag on the vnode (think bit set) during the "create" phase to mark elements, and use it to dispatch to That would let us cut down the branches in the common cases, and will probably boost perf. The flag would also let us drop a |
@porsager @pygy @barneycarroll and other interested parties: I've filed #2340 as an alternative proposal to this. |
@pygy I'm having trouble getting what you're trying to say. Could you elaborate a little, especially with regards to context? I'm having trouble tracing what your comment is in reply to.
Just thought I'd point out I've been considering adding this for a while for various things. Mainly, it's because I can avoid type checks for existing data, but pretty much every time I've looked into using it for a feature, I've noticed it's been one of a couple things:
Also, about the only real precedent we had for a boolean state option, |
I think I'm interpreting @pygy right in the notion that this code is horribly forked at the minute and the |
As per discussion on Gitter between @barneycarroll and I, we've decided to just document how we do resolution and encourage |
@isiahmeadows: @barneycarroll is correct: I mean that Not having to worry about form fields or custom elements would make the common case faster. |
Also, the latest RC seems to work just fine with custom elements and arbitrary props in the browser... The mocks need to support custom elements if we want to ensure there are no regressions... |
@pygy They already kinda do in that they don't validate their input at all. It's why our We could stand to use some tests of the mock itself in this area, so we know it works as we expect it to. But as it stands, I don't think the DOM mock itself needs patched. |
To comply with custom-elements and most likely also user expectations any non primitive should be set as a property on the dom element instead of as attributes
Description
I've added a check to set value as a property on the dom element if the type is not a primitive
Motivation and Context
Fixes custom-elements compliance (#2220) which should have been added in #2221 , but I couldn't find where.
How Has This Been Tested?
All existing tests passes, and new tests for non primitives to be set as properties have been added
Types of changes
Checklist:
docs/change-log.md