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.).

The frameworks we aim for the most compatibility are:

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

Vanilla HTML

(a.k.a. No framework)

Angular 1.x

TBD

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 16+

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

What about 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 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()

Upate 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