What is this?

Angular in my React?

Who We Are

Ryan Chenkie

Brad McAlister

@ryanchenkie

@sonicparke

Companies and developers are narrowing in on the big three

We often think it looks like this

Enterprise Corporation, Inc

We miss AngularJS, LLC

Hipster Startup, LLC

In reality, it looks like this

Foo Corp

Foo Team #2

Foo Corp Acquisition

Another Foo Corp Aquisition

Bar Corp Acquisition

Bar Corp ???

Bar Corp Legacy App

Old Bar Corp Acquisition

Sharing Code Between Apps is Hard

What if we could:

  • Use a custom element just like a native HTML element
  • Have a "private" DOM
  • Share components between apps, regardless of the framework

Web Components

To create a Web Component, we use the Custom Elements API

<my-element></my-element>

What are people saying about Web Components?

Nothing beats the native habitat for a component

But what if we need to share components?

Angular Elements Provide the Best Experience for Authoring Custom Elements

Why Build with Angular Elements?

  • Developer experience (Angular APIs, CLI)
  • Documentation and content
  • Best overall support (community) 

How it works

Imagine an ideal world with us.

NASA loves Angular

International Space Station

a.k.a. ISS

VERY IMPORTANT PIECE OF EQUIPMENT

DEMO

AMERICAN

Space Station

INTERNATIONAL

Space Station

 

The best solution?

 A web component made with Angular Elements

Angular Component

Angular Element

to

transforming

ng add @angular/elements

Add Angular Elements

export class AppModule {
  constructor(private injector: Injector) {}
  ngDoBootstrap() {
    const el = createCustomElement(
        TemperatureGaugeComponent, 
        { injector: this.injector }
    );
    customElements.define(
        'iss-temperature-gauge', 
        el
    );
  }
}

Bootstrap

entryComponents: [
  TemperatureGaugeComponent
]

It's Dynamic

[...]
<body>

  <iss-temperature-gauge
    unit="fahrenheit"
    station-component="discombobulator"
  ></iss-temperature-gauge>

</body>

Replace

<app-root>
ng serve

of course...

We need polyfills.

// Used for browsers with partially native support of Custom Elements
import '@webcomponents/custom-elements/src/native-shim';

// Used for browsers without a native support of Custom Elements
import '@webcomponents/custom-elements/custom-elements.min';
npm install @webcomponents/custom-elements

polyfills.ts

if (

) {

}

*Might* need polyfill.

// Used for browsers without a native support of Custom Elements
import '@webcomponents/custom-elements/custom-elements.min';
npm install @webcomponents/custom-elements

polyfills.ts

if (

) {

}

if (

) {

}

Differential Loading?

Nope. Roll your own.

DEMO

Distribution

ngx-build-plus

+

Add ngx-build-plus

ng add ngx-build-plus
"builder": "ngx-build-plus:browser"

Updates Builder

New Flags

--single-bundle --keep-polyfills

Update Build Script

"ng build --prod --single-bundle --keep-polyfills"
npm run build

Build

Package with NPM

{
  "name": "iss-elements",
  "version": "0.0.1"
}
npm run npm-pack

Pack It

Ready for Publishing

My Favourite:

Canadian Space Agency

The CSA uses React for their mission control

They want to share the component with NASA and not need to rebuild it

Consuming the Element in React is Easy

npm install <package>
<iss-temperature-gauge
    unit="celsius"
    station-component="discombobulator"
><iss-temperature-gauge/>

Inputs work as we'd expect

<iss-temperature-gauge (hiTemp)="...">

If we want to listen for an event, it's tempting to do something like this

Listening for Outputs Requires Extra Work

<iss-temperature-gauge ref={...}>
class App extends Component {

  issTempComponent;

  handleRef = refNode => {
    this.issTempComponent = refNode;
  };

  render() {...}
}
<iss-temperature-gauge ref={this.handleRef} />
class App extends Component {

  componentDidMount() {
    this.issTempComponent.addEventListener('hiTemp', e => {
      this.setState(...)
    });
  }

  componentWillUnmount() {
    this.issTempComponent.removeEventListener('hiTemp');
  }

  ...

  render() {...}
}
this.component.addEventListener('hiTemp', e => {
  this.setState({
    hasHighTemp: e.detail.alert,
    name: e.name,
    temperature: e.temperature
  })
});

DEMO

Because it's a web component, we can use it many more places than just React

Is this a good idea?

Why it might not be

  • Bundle Size
  • Ivy isn't here yet...
  • If you need to do content projection
 
 
  • Upgrading from AngularJS
  • Framework experience and familiarity
  • Ivy is coming
 
 
 

Why it might be

Angular + React

the Easy Way

npx create-nx-workspace my-nx-app --preset=empty

ng g app angularapp --framework=angular

ng g app reactapp --framework=react
ng g lib my-lib --framework=none
@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  bootstrap: [AppComponent]
})
export class AppModule {}

Juri Strumpflohner

Special Thanks

Manfred Steyer

LINKS TO EVERYTHING

bit.ly/ng-de-elements

ryanchenkie.com

ngauthbook.com

Thanks!!

Ryan Chenkie

Brad McAlister

@ryanchenkie

@sonicparke

What is this? Angular in my React?

By Ryan Chenkie

What is this? Angular in my React?

Reusable components are a great idea. That is, until you find yourself working in a React app and you’re unable to reuse the great Angular components you’ve already built. Thankfully, there’s a way around this. If you need to support multiple frontend frameworks, you can harness the power of Angular Elements to do just that and build reusable shared components that will drop right in your app. In this talk, we’ll show you how you can manage components across different frontend frameworks and keep everyone happy.

  • 1,108