Search code examples
jwplayershadow-domcustom-element

jwplayer doesn't play well in Angular Elements


I have this Angular component with embedded jwplayer that works fine. When I try to create a custom element out of it with Angular Elements or try to use "encapsulation: ViewEncapsulation.Native", the jwplayer will fail to initialize. jwplayer is loaded, I can see it in window object.

core.js:1604 ERROR TypeError: jwplayer(id).setup is not a function
    at t.setupPlayer (jw-player.js.pre-build-optimizer.js:70)
    at HTMLScriptElement.S (zone.js:1188)
    at t.invokeTask (zone.js:421)
    at Object.onInvokeTask (core.js:4034)
    at t.invokeTask (zone.js:420)
    at e.runTask (zone.js:188)
    at e.invokeTask [as invoke] (zone.js:496)
    at k (zone.js:1540)
    at HTMLScriptElement._ (zone.js:1566)  

Solution

  • The reason is the loaded library (https://content.jwplatform.com/libraries/6gLLM4B1.js). It looks up the video element using document.getElementById(...) and it also uses document.body sometimes. However, the video element is the JwPlayerComponent and if you activate Shadow DOM on the root component this element is hidden within the Shadow DOM.

    On the other side, you could provide it as an Angular Element/ Custom Element using ViewEncapsulation.Native. To make this work, I had to introduce some modifications to the project:

    • Remove the selector b/c it conflicts with the name of the custom element (// selector: 'wu-player-element')
    • Also remove the bootstrap section of your module (//bootstrap: [AppComponent])
    • Modify your tsconfig.app.json: Add "target": "es2015", b/c Custom Elements do not work with the way, TypeScript downlevels classes to ES5

    If you need ES5 nethertheless, you could use a polyfill (native-shim.js), see: https://www.softwarearchitekt.at/post/2018/07/13/angular-elements-part-i-a-dynamic-dashboard-in-four-steps-with-web-components.aspx