Reputation: 85
I try to learn WebComponents, and it's not easy as that technology is unclear yet and a bit underdeveloped. The main issue I have with it, it's based on JavaScript Class syntax, where I try to keep code in a functional/prototype programming way.
Then made this script. Custom Element exists, inherits HTMLElement methods, shadowDom, and also styling does work.
But...
I encountered error:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<x-foo></x-foo>
<script>
function Xfoo( str ) {
this.str = str;
};
let XFoo = "x-foo";
XFoo.constructor = "x-foo";
HTMLElement.prototype.XFoo = new Xfoo();
customElements.define( XFoo, XFoo.constructor );
const xfoo = document.getElementsByTagName(XFoo)[0];
console.log( xfoo );
const shadow = xfoo.attachShadow( { mode: "open" } );
const styleNode = document.createElement("style");
styleNode.textContent = `
* {
background-color: blue;
font-size: 32px;
}
`;
shadow.appendChild( styleNode );
const text = document.createElement("span");
text.textContent = "content";
shadow.appendChild( text );
</script>
</body>
</html>
Uncaught TypeError: Custom element constructor returned a wrong element
<anonymous>
I tried to look through documentation, but can't find what that constructor element should return, so I can just return it... Or figure out the way to make it properly.
EDIT: Summary - This Script Works. I just want to get rid of this error. Get to know how to fix it or make it better, avoiding OOP and Class based code as much as I can.
Thanks for any help in advance.
Upvotes: 0
Views: 1185
Reputation: 85
I found the solution yesterday on the same Issue as @abraham in his answer.
function CustomElement() {
return Reflect.construct(HTMLElement, [], CustomElement);
}
Object.setPrototypeOf(CustomElement.prototype, HTMLElement.prototype);
Object.setPrototypeOf(CustomElement, HTMLElement);
customElements.define('custom-element', CustomElement);
It seems to be possible, and I need to look through all that topic + MDN documentation to get how does all of their solution works.
Upvotes: 0
Reputation: 47853
It's essentially impossible to write web components without ES6 classes. If you do find a solution that works you'll never be able to search for documentation or guides and if you run into issues there won't be Stack Overflow posts about how to fix them.
It's not possible to use custom elements without ES6 classes. That was a design decision necessary to achieve consensus at the January face-to-face meeting.
It looks like it might be possible, but the implementation is very convoluted.
function MyEl() {
return Reflect.construct(HTMLElement,[], this.constructor);
}
MyEl.prototype = Object.create(HTMLElement.prototype);
MyEl.prototype.constructor = MyEl;
Object.setPrototypeOf(MyEl, HTMLElement);
MyEl.prototype.connectedCallback = function() {
console.log('my-el connected');
};
customElements.define('my-el', MyEl);
document.body.appendChild(document.createElement('my-el'));
If you are really set on not writing classes, I'd recommend you check out haunted. It's got a nice pattern for writing components without writing classes.
function Counter() {
const [count, setCount] = useState(0);
return html`
<div id="count">${count}</div>
<button type="button" @click=${() => setCount(count + 1)}>
Increment
</button>
`;
}
customElements.define('my-counter', component(Counter));
Upvotes: 1
Reputation: 21183
The Custom Elements API is class based inheritance.
You are using a lot of oldskool JavaScript.
You probably looked at very old blogs, referencing the old V0 version of Web Components.
Which mainly was a Google party only, never a standard.
It is better to discard any blogs or StackOverflow posts over 4 years old,
just to be sure you are looking at V1 standard Web Components information, created by Apple+Mozilla+Microsoft+Google.
MDN and Mozilla documentation are 99,9% accurate.
You code should be something like this:
customElements.define("x-foo", class extends HTMLElement {
constructor(){
super().attachShadow({mode:"open"})
.innerHTML = `<style>
:host{
background-color: blue;
color:gold;
font-size:32px;
}
</style>
Hello Web Component!
`
}
})
<x-foo></x-foo>
Upvotes: 1