Angular + Polymer
Clone or download
Latest commit 1ea04d6 Sep 11, 2018
Permalink
Failed to load latest commit information.
bin fix(bin): read compilerOptions target from extended tsconfig.json #85 Sep 11, 2018
forms test: fix issue with microtasks not draining Sep 5, 2018
polyfills docs: add note about angularCompilerOptions for dynamic bootstrap mod… Sep 11, 2018
src test: add remaining tests Sep 5, 2018
styles fix(styles): AoT issue with IncludeStyles decorator Sep 10, 2018
templates fix(templates): property bindings fail when there is no hostProps (ex… Aug 29, 2018
util feat(util): add optional synchronous callback to whenSet Aug 24, 2018
.editorconfig chore: initial commit Mar 31, 2017
.gitignore test: restore karma and add templates/util tests Aug 22, 2018
.prettierrc.json feat: v3 rewrite with Polymer 3 support Aug 1, 2018
.travis.yml test: restore karma and add templates/util tests Aug 22, 2018
CHANGELOG.md chore(release): 3.0.2 Sep 11, 2018
LICENSE.txt feat: v3 rewrite with Polymer 3 support Aug 1, 2018
README.md docs: add note about angularCompilerOptions for dynamic bootstrap mod… Sep 11, 2018
UPGRADE.md docs: add note about angularCompilerOptions for dynamic bootstrap mod… Sep 11, 2018
init.spec.ts test: fix styles sometimes disappearing Aug 28, 2018
karma.conf.js test: disable coverage on CI to help with disconnects Sep 5, 2018
package-lock.json chore(release): 3.0.2 Sep 11, 2018
package.json chore(release): 3.0.2 Sep 11, 2018
public_api.ts feat: added polyfill module and updated docs Aug 9, 2018
tsconfig.json feat(styles): rename shadycss path to styles, add Polymer style modul… Aug 24, 2018

README.md

Origami

Origami is the art of folding paper with angles to form beautiful creations.

Angular + Polymer

NPM Package

Test Status

Summary

Angular and custom elements are BFFs. With Polymer, there are a few gaps that Origami fills. The library is divided into several modules that can be imported individually to address these gaps.

To setup Origami, follow these steps:

  1. Install and import OrigamiModule
  2. Set up polyfills
  3. Prepare dependencies if targeting ES5
  4. Read the Usage Summary

Install

Upgrading from Origami v2? Follow this guide.

npm install @codebakery/origami

Import each module as described in the links above, or if you need all of the modules you can simply import OrigamiModule. Include CUSTOM_ELEMENTS_SCHEMA to enable custom elements in Angular templates.

import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { OrigamiModule } from '@codebakery/origami';
import { AppComponent } from './app.component';

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

Polyfills

Polyfills are needed to support browsers that do not support all webcomponent features. To quickly set up polyfills, use the Origami CLI.

npm install @webcomponents/webcomponentsjs
./node_modules/.bin/origami polyfill

Wait for WebComponentsReady

Some imports (such as Polymer's TemplateStamp mixin) have side effects that require certain features to be immediately available. For example, TemplateStamp expects HTMLTemplateElement to be defined. These imports should be deferred until after webcomponentsReady() resolves.

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { webcomponentsReady } from '@codebakery/origami/polyfills';

webcomponentsReady()
  .then(() => {
    // requires "module: "esnext" in tsconfig.json "compilerOptions" and
    // "angularCompilerOptions": {
    //   "entryModule": "app/app.module#AppModule"
    // }
    return import('./app/app.module');
  })
  .then(({ AppModule }) => {
    platformBrowserDynamic().bootstrapModule(AppModule);
  });

Prepare Dependencies (ES5 only)

Angular will not transpile node_modules/, and a common pattern among webcomponents is to be distributed as ES2015 classes. Use Origami's CLI to effeciently transpile dependencies to ES5 or back to ES2015 before building.

Example:

origami prepare es5 node_modules/{@polymer/*,@vaadin/*,@webcomponents/shadycss}

# to restore to ES2015
origami prepare es2015 node_modules/{@polymer/*,@vaadin/*,@webcomponents/shadycss}

# for more info
origami --help

Note that @webcomponents/webcomponentsjs should not be transpiled. However, @webcomponents/shadycss should be if it's used.

The CLI can also restore the previous ES2015 files for projects that compile to both targets.

It is recommended to add a script before ng build and ng serve tasks in package.json.

{
  "scripts": {
    "prepare:es5": "origami prepare es5 node_modules/{@polymer/*,@vaadin/*,@webcomponents/shadycss}",
    "prepare:es2015": "origami prepare es2015 node_modules/{@polymer/*,@vaadin/*,@webcomponents/shadycss}",
    "start": "npm run prepare:es5 && ng serve es5App",
    "start:es2015": "npm run prepare:es2015 && ng serve es2015App",
    "build": "npm run prepare:es5 && ng build es5App --prod",
    "build:es2015": "npm run prepare:es2015 && ng build es2015App --prod"
  }
}

Usage Summary

Angular Form Support

Add the origami attribute to any custom element using [ngModel], [formControl] or [formControlName].

import { Component } from '@angular/core';
import '@polymer/paper-input/paper-input';

@Component({
  selector: 'app-component',
  template: `
    <div>Angular value: {{value}}</div>
    <paper-input [(ngModel)]="value" origami></paper-input>
  `
})
export class AppComponent {
  value: string;
}

ShadyCSS Support

Enables the use of CSS custom properties in Angular styles on browsers that do not support them via ShadyCSS, with some limitations.

import { Component } from '@angular/core';
import '@polymer/paper-button/paper-button';

@Component({
  selector: 'app-component',
  styles: [
    `
      paper-button {
        --paper-button-ink-color: blue;
      }
    `
  ],
  template: `
    <paper-button>Blue Ink!</paper-button>
  `
})
export class AppComponent {}

Style Modules

Allows for style modules defined in Polymer to be injected into Angular components.

import { Component } from '@angular/core';
import { IncludeStyles } from '@codebakery/origami/styles';
import '@polymer/iron-flex-layout/iron-flex-layout-classes';

@IncludeStyles('iron-flex')
@Component({
  selector: 'app-component',
  styles: [':host { display: block; }'], // See Limitations
  template: `
    <div class="layout horizontal">
      <div class="flex">Column 1</div>
      <div class="flex">Column 2</div>
    </div>
  `
})
export class AppComponent {}

Polymer <template> Stamping

Call polymerHost() and add it to the providers for a component that uses Polymer's data binding syntax in <template> elements. Add ngNonBindable to all <template> elements.

import { Component } from '@angular/core';
import { polymerHost } from '@codebakery/origami/templates';
import '@polymer/iron-list/iron-list';

@Component({
  selector: 'app-component',
  template: `
    <iron-list [items]="items">
      <template ngNonBindable>
        <div on-click="itemClicked">
          <div>[[getLabel(item)]]</div>
        </div>
      </template>
    </iron-list>
  `,
  providers: [polymerHost(AppComponent)]
})
export class AppComponent {
  items = [1, 2, 3];

  getLabel(item: number) {
    return `# ${item}`;
  }

  itemClicked(event: Event) {
    console.log(event);
  }
}