Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

post: angular elements #241

Merged
merged 6 commits into from
May 29, 2018
Merged

post: angular elements #241

merged 6 commits into from
May 29, 2018

Conversation

cexbrayat
Copy link
Member

@cexbrayat cexbrayat commented Oct 29, 2017

This is just in case the PR angular/angular#19469 lands in ng 5 just before the release.
(the Angular team has been working on it the whole weekend, so that may be the goal).
The plan is then to release this post at the same time as the one on ng 5 and link them.

If angular elements lands later, we'll release it separately.

Feedback is welcome if you have time to review (in case we have to release it with ng 5).

This is on top of #238 , review only the last commit

@cexbrayat cexbrayat requested review from clacote and jnizet October 29, 2017 23:33
Copy link
Member

@jnizet jnizet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. Do you know the reason why they decided to push that?

but there is a bit of "plumbing" to do (you have to write an ES6 class with a constructor that follows some rules,
then observe the attributes that can change, then implement the correct lifecycle methods defined in the specification).

That why Angular 5 introduces `@angular/elements`!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is why

// listen to the custom event
ponyComponent.addEventListener('selected', event => console.log('selected!', event));

You can even create new component and insert them, they will be automatically upgraded to custom element (and the inner PonyComponent will be instantiated)!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new components

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to custom elements

## Support for Angular 5 and its new compiler, AoT by default!

This is probably the biggest feature of this release!
As Angular 5 ships with an improved compiler (check out our article about that if you missed it),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to have a link to the article here. (link)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review :) You're right, the link to our other (unpublished) article is needed here. It's pretty much ready, we are just waiting for the official release!

Angular Elements are classic components packaged as Custom Elements.

When you package an Angular Component as an Angular Element,
you can the use it like a standard Custom Element.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can then use like

setTimeout(() => ponyComponent.ponyName = 'Pinkie Pie', 3000);

// listen to the custom event
ponyComponent.addEventListener('selected', event => console.log('selected!', event));
Copy link

@gkalpak gkalpak Oct 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might not want to go into that much detail here, but event will be a CustomEvent, which means that the emitted value will be on event.detail. This is typical for Custom Elements.

(BTW, I've put the source code from the PR into this stackblitz project if you want to have a play.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thxs for the review @gkalpak (I hope the rest of the post is accurate enough!).

I'll update the example to include event.detail. I have my own project (building your PR from source) but I'll add a link to your Stackblitz project in the post if you don't mind, so the readers will be able to play with it 👍 .

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, no problem. Hm...actually, it is better to use this link (which I will not modify further).
Or you can use that link, which looks a little prettier (using @angular/material components as custom elements 😃).

The rest of the post looks accurate enough 👍 (given the volatile state of the @angular/elements atm 😃). The API is definitely going to change (in subtle but breaking ways 😁). One thing you might want to mention is that you need to include custom-element-specific polyfills on all browsers (for different reasons).

(BTW, I don't think this will land for 5.0.0.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 No worries, I'm reviewing your PR regularly and I'll update the blog post.

Regarding the polyfill needed, I noticed that I had to use native-shim. Is it the one you're talking about? I was hoping that setting the compilation target to ES2015 would be enough as I was using a class for my component, but that's because of Angular code right?

Copy link

@gkalpak gkalpak Oct 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm reviewing your PR regularly and I'll update the blog post

I mean even after the PR lands. There will be follow-up PRs. The plan is to merge the original PR and iterate (but probably after 5.0.0).
But you are apparently doing a great job keeping an eye on us (which is awesome btw), so I am sure you will find out the moment it happens 😁

WRT to polyfills, it depends on your browser's needs. My preliminary findings:

  • IE9-10 require a MutationObserver polyfill and an Object.setPrototypeOf polyfill (but one that can cope with getter/setter descriptors).
  • Browsers without native customElements support (e.g. Edge, Firefox, IE9-11, Safari) require @webcomponents/custom-elements/custom-elements.min.js.
    (There are some issues on Safari 7-9 which I haven't solved yet, so they might need more polyfills.)
  • Browsers with native customElements support (e.g. Chrome, Opera) require @webcomponents/custom-elements/src/native-shim.js, which (as you said) is for allowing ES5 functions to be used as custom elements. (According to the spec, only ES2015 class can be used.)
    Theoretically, you should not require that if compiling to ES2015 and using the ES2015 Angular sources (which are published as well). But I haven't tried that yet.

(I have included the polyfills I used for running the PR tests at the bottom of this file.)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't happen 😕

When I build my PR locally, I can see that the es2015 sources (dist/packages-dist/elements/esm2015/elements.js) look correct. I.e. I see the following:

class NgElementImpl extends HTMLElement {
  ...
  constructor() {
    super();
  ...
}

createNgElementConstructor(...) {
  ...
  class NgElementConstructorImpl extends NgElementImpl {
    constructor() {
      super(...);
   ...
}

Based on your error, it seems that you are using the non-es2015 sources.
Do you have a repo where I can reproduce the error?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simple repro here

It is using my own build snapshots, but they are based on your last commit. When running yarn package & http-server you can see the error. It looks like my build does not use the esm2015 sources, I'm probably just missing a setting somewhere...

Copy link

@gkalpak gkalpak Nov 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First of all, your demo helped me find out that package.json#es2015 was misconfigured for @angular/elements (it contained esm15 instead of esm2015). I fixed that on the PR. 😄

With that fixed, you need to make sure the es2015 (not the es5) sources are used in the bundle. I didn't look into if/how you can do it with webpack, but I know @angular/cli knows how to do it, so here is a demo that shows @angular/elements working without native-shim (yarn && yarn start).

I added a small postinstall script that fixes up @angular/elements/package.json.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you wanted to do it without the cli, you need to either load directly from @angular/elements/esm2015/elements or configure webpack to take package.json#es2015 into account when resolving a package. Here is how the cli configures webpack, for example.
See here for more info on what the conventions are for supporting different formats.

Shout out to @filipesilva for providing all the info 😁

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gkalpak That indeed works with the proper Webpack config and using your fixed PR. Happy that it helped to catch this bug!
I'll update the article to include a few things about the polyfills.

@cexbrayat
Copy link
Member Author

@jnizet @clacote I updated the Angular Elements article with the correct code from v6 (see https://github.com/cexbrayat/ng-elements/commit/ce175b4b738c40dc12b90fb4b612a634c88e2294 for the demo repo that I use). I plan to publish the article shortly after the v6 release (first the article about ng v6, then cli v6, then this one).

@clacote clacote force-pushed the master branch 2 times, most recently from 94d1741 to 77e95ba Compare May 7, 2018 22:55
@cexbrayat
Copy link
Member Author

@jnizet @clacote Can I have a last review on this one before we publish?

Copy link
Member

@clacote clacote left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor suggestions

@@ -0,0 +1,129 @@
---
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This post/file needs to be removed

layout: post
title: Angular Elements
author: cexbrayat
tags: ["Angular 2", "Angular", "Angular 4", "Angular 5", "Angular 6", "Angular CLI"]
Copy link
Member

@clacote clacote May 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe that should be reordered (order is preserved at display time: "Angular 6", "Angular 5"...) and maybe add "Web Components" and/or "Custom Elements"


I deep dived into the [official specification](https://w3c.github.io/webcomponents/spec/custom/)
to learn a bit more about the details of Custom Elements.
You can of course build your own Custom Elements with vanilla JavaScript
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your own Custom Elements -> your own Custom Element (singular)

so I would not recommend using it in production yet.
But this time will come!

Check out our [ebook](https://books.ninja-squad.com/angular), [online training (Pro Pack)](https://angular-exercises.ninja-squad.com/) and [training](http://ninja-squad.com/training/angular) if you want to learn more!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


Sometimes you don't want a full Angular app. Sometimes you just want to build a widget.
Or maybe you have several teams, some using React, Vue and others Angular.
Right now it's not really easy to share just one Angular component,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to share -> to integrate

// get the ES6 class
const PonyElement = createCustomElement(PonyComponent, { injector });
// use it to register the custom element
customElements.define('ns-pony', PonyElement);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is customElements here? A standard function provided by the browser on window (apparently yes). So I would make that clear by using window.customElements

@cexbrayat
Copy link
Member Author

Fixed: ready to merge and publish tomorrow morning

@cexbrayat cexbrayat merged commit 27c3da2 into master May 29, 2018
@cexbrayat cexbrayat deleted the post/ng-elements branch May 29, 2018 06:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants