Skip to content

Framework Compatibility

Ryan Johnson edited this page May 20, 2019 · 20 revisions

Even though HelixUI strives to remain platform-agnostic, we also want to build functionality in a way that provides the least resistance for integration into a consumer's technology stack. As such, you should avoid implementing any business logic into new functionality (no API calls, no permission/authorization logic, no URLs, etc.).

Click one of the links below to read about HelixUI compatibility for various frameworks.

Framework Versions Supported?
Vanilla HTML / No Framework n/a YES
AngularJS 0.x - 1.x no
Angular* 2.0+ YES
React 15 15.x no
React 16+ 16.0+ YES
VueJS 2.x 2.x YES

Keep reading to learn more about framework compatibility issues and strategies to correct or work around them.

Vanilla HTML

(a.k.a. No framework)

AngularJS 1.x

AngularJS (0.x - 1.x) is not supported.

However, according to custom-elements-everywhere.com, AngularJS 1.7.8 has perfect compatibility with custom elements. Compatibility with earlier versions of AngularJS 1.x are unknown, though.

If you are using AngularJS, you might want to consider upgrading or porting to a modern framework. As announced by the AngularJS team, AngularJS 1.7 is the last feature release and will remain in a 3-year Long Term Support period. On June 30, 2021, AngularJS will reach the end of its support.

Angular 2+

@angular/cli

If you want use @angular/cli to bootstrap your application, you'll need to make sure to do the following to ensure maximum compatibility with HelixUI.

  1. copy node_modules/helix-ui/ assets to src/assets/helix-ui/
  2. copy node_modules/@webcomponents/webcomponentsjs/ assets to src/assets/webcomponentsjs/
  3. update src/index.html contents with official Helix layout markup
  4. make sure <link> and <scripts> in src/index.html point to files in src/assets/helix-ui and src/assets/webcomponentsjs
  5. add CUSTOM_ELEMENTS_SCHEMA to the list of schemas in src/app/app.module.ts (see snippet below)
  • Configures angular that to allow 3rd-party custom elements.
/* 
 * src/app/app.module.ts 
 */
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent],
  schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
})
export class AppModule { }

React 15

React 15 is not supported.

It lacks support for the slot attribute, which is required in order to take advantage of Light DOM redistribution into Shadow DOM slots. For this redistribution to happen, the slot attribute needs to be present in the rendered markup.

React 15 ignores unknown attributes and slot isn't a known attribute, so it's missing from the rendered markup. This results in Light DOM elements being redistributed into the wrong Shadow DOM slots.

Assume the following React/JSX Template:

<hx-custom-element>
  <p id="first">
    I will be redistributed into the default, unnamed slot in Shadow DOM.
  </p>

  <p id="second" slot="extra">
    I should be redistributed into the "extra" slot in Shadow DOM.
    React 15 doesn't include [slot="extra"], so I get redistributed 
    into the default, unnamed slot instead.
  </p>
</hx-custom-element>

React 15 Renders the following: (notice how slot is missing from <p id="second">)

<hx-custom-element>
  <p id="first">...</p>
  <p id="second">...</p>
</hx-custom-element>

React 16+ Renders the following: (the slot attribute is still present)

<hx-custom-element>
  <p id="first">...</p>
  <p id="second" slot="extra">...</p>
</hx-custom-element>

React 16+

  • TODO: Using ref to attach event listeners
  • Warning: React's synthetic events violate non-bubbling specifications.

React Component Lifecycle

All HTMLElement (custom element) lifecycle methods are executed in render()

Mount Phase

  1. React.Component - constructor
  2. React.Component - componentWillMount()
  3. React.Component - render()
    1. HTMLElement - create/connect
      1. constructor
      2. attributeChangedCallback()
      3. connectedCallback()
  4. React.Component - componentDidMount()

Unmount Phase

  1. React.Component - componentWillUnmount()
  2. React.Component - render()
    1. HTMLElement - disconnect 2. disconnectedCallback()

Update Phase

  1. React.Component - componentWillUpdate()
  2. React.Component - render()
    1. HTMLElement - disconnect
      1. disconnectedCallback()
    2. HTMLElement - create/connect
      1. constructor
      2. attributeChangedCallback()
      3. connectedCallback()

Vue 2.x

  • FYI: nesting a <div> within a <p> seems to break data binding in VueJS 2.5
    • (codepen example)
    • trying to track down the reason why this breaks
    • To be continued...

Resources

Clone this wiki locally