emberjs / ember.js

Ember.js - A JavaScript framework for creating ambitious web applications
https://emberjs.com
MIT License
22.45k stars 4.21k forks source link

WebComponents extending native elements using the `is` attribute does not work in Ember templates #18508

Closed melvinroest closed 1 year ago

melvinroest commented 4 years ago

I detailed the question on StackOverflow which includes the Ember Twiddle and standalone HTML runnable code snippet as baseline comparison.

In my project I used Ember 3.12

https://stackoverflow.com/questions/58529308/emberjs-and-web-components-extend-an-existing-html-tag-within-an-initializer-i

melvinroest commented 4 years ago

I currently determined that the "is" attribute is correctly parsed by Glimmer, so that's not the issue.

Screenshot 2019-10-24 at 10 04 22
melvinroest commented 4 years ago

I'm done.

I updated the StackOverflow question with an answer, what I think is happening, how to verify that for yourself, a high level situation as a JSFiddle, and a hacky workaround including a rationale on why I chose that (hacky) workaround.

I learned a lot and it was a lot of fun to poke around in Glimmer VM. For now, I'm going to rewrite the web component that I have to an Ember component :)

chancancode commented 4 years ago

I think you are right. If there is an is attribute, we need to call document.createElement("p", { is: "..." }) instead of el = document.createElement("p"); el.setAttribute("is", "...");

sandstrom commented 1 year ago

I'm doing some issue gardening 🌱🌿 🌷 and came upon this issue.

This issue has been open for a while without anyone jumping in to fix it. The reality is that unless you want to fix the bug itself, it will likely stay that way.

The time of core team members is very limited, and we all want them to focus on moving the framework forward (high-leverage things), leaving fixing of edge case bugs to "fringe volunteers", such as you and me.

By closing some old issues we reduce the list of open issues to a more manageable set. Let me know if you think this is a mistake and that the issue should stay open.

MoonScript commented 10 months ago

@melvinroest I'm poking around in the current Ember source code, but I can't find any of the code you referenced in your Stackoverflow post. Any chance you could point me in the right direction, because I'd love to fix this and submit a PR back to Ember?

chancancode commented 10 months ago

I think the code you are looking for would be in glimmer-vm.

The bottomline is we currently call document.createElement() and then setAttribute()s separately, which is fine, except in the case of the special is="..." which is a really special argument that must be passed at the same time as the createElement() call, once you created the element there is no way to upgrade it later.

So that means we probably need to:

  1. detect the cases at wire-format compilation where we can statically see <some-html-element ... is="..."> and emit a slightly different WF opcode for it
  2. disallow is={{...}}, at least for now
  3. disallow passing is="..." or is={{...}} to components (local variables or imported in-scope values) that later gets applied via ...attributes, at least for now

I think those easily doable, whereas supporting the dynamic cases are a fair bit harder and probably quite uncommon. If you want to take a stab at that you would go to http://github.com/glimmerjs/glimmer-vm, add a failing test and go from there. I personally don't have a lot of bandwidth but there are others that can perhaps help on #dev-glimmer-vm on Discord.

Alternatively if you are just looking for a quick around to unblock yourself in the app, you can create the element manually in JS and leverage the fact that {{...}} can render DOM nodes (.gjs show but you can do that without too, as a helper or getter on the component class):

class CustomElementIntegrationPoint extends Component {
  get customElement() {
    let element = document.createElement("div", { is: ... });
    element.setAttributes(...);
    return element;
  }

  <template>{{this.customElement}}</template>
}

You lose some features like ...attributes but you can probably work around that.