I'm running into trouble getting a simple web component to work when transpiled to ES5. It appears to function perfectly fine under chrome, Edge, and Firefox, but IE11 is failing in the component's constructor with "The custom element constructor did not produce the element being upgraded."
The excellent work of Oliver Krull below has clearly pinned down the problem to Typescript's compiler output. Is it possible to make it work?
The original source (in TypeScript):
import "./AppDrawer.less"
class AppDrawer extends HTMLElement {
get open() {
return this.hasAttribute("open");
}
set open(val: boolean) {
val ? this.setAttribute("open", '') : this.removeAttribute('open');
}
get disabled() {
return this.hasAttribute("disabled");
}
set disabled(val: boolean) {
val ? this.setAttribute("disabled", '') : this.removeAttribute('disabled');
}
static get observedAttributes() { return ["open"] };
constructor() {
super();
}
connectedCallback() {
this.addEventListener("click", () => {
this.open = !this.open;
})
this.textContent = this.open ? "OPEN": "CLOSED";
}
attributeChangedCallback(attr, oldVal, newVal) {
this.textContent = this.open ? "OPEN": "CLOSED";
}
}
customElements.define("app-drawer", AppDrawer)
The output (bundle.js
):
(function () {
'use strict';
function __$styleInject(css) {
if (!css) return;
if (typeof window == 'undefined') return;
var style = document.createElement('style');
style.setAttribute('media', 'screen');
style.innerHTML = css;
document.head.appendChild(style);
return css;
}
__$styleInject("app-drawer {\n color: red;\n}\n");
function __extends(d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var AppDrawer = (function (_super) {
__extends(AppDrawer, _super);
function AppDrawer() {
_super.call(this);
}
Object.defineProperty(AppDrawer.prototype, "open", {
get: function () {
return this.hasAttribute("open");
},
set: function (val) {
val ? this.setAttribute("open", '') : this.removeAttribute('open');
},
enumerable: true,
configurable: true
});
Object.defineProperty(AppDrawer.prototype, "disabled", {
get: function () {
return this.hasAttribute("disabled");
},
set: function (val) {
val ? this.setAttribute("disabled", '') : this.removeAttribute('disabled');
},
enumerable: true,
configurable: true
});
Object.defineProperty(AppDrawer, "observedAttributes", {
get: function () { return ["open"]; },
enumerable: true,
configurable: true
});
AppDrawer.prototype.connectedCallback = function () {
var _this = this;
this.addEventListener("click", function () {
_this.open = !_this.open;
});
this.textContent = this.open ? "OPEN" : "CLOSED";
};
AppDrawer.prototype.attributeChangedCallback = function (attr, oldVal, newVal) {
this.textContent = this.open ? "OPEN" : "CLOSED";
};
return AppDrawer;
}(HTMLElement));
customElements.define("app-drawer", AppDrawer);
}());
And my HTML:
<!doctype html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.0-rc.8/webcomponents-lite.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.0-rc.8/custom-elements-es5-adapter.js"></script>
<script src="bundle.js"></script>
</head>
<body>
<app-drawer open disabled></app-drawer>
</body>
</html>
In order to get custom elements v1 working cross browser we need to add this native-shim (here more infos about it).
This works well in all major browsers (edge, safari, firefox etc..) but doesn't in ie11!
When we try to import it in ie11 we get a bunch of syntax errors because the shim is written with some es6.
A simple workaround is to compile the shim to es5 and add it in addition of the es6 version (first es6, then es5 to omit errors).
This isn't the cleanest solution, but at least it works.
I created a repo with a working example (your app-drawer (removed the disabled
attribute because of conflicts)).
Again, it's not verry clean but it works ;-)