Use Angular components in AngularJS applications with Angular Elements

Share this video with your friends

Send Tweet
Published 4 years ago
Updated 3 years ago

When migrating AngularJS (v1.x) applications to Angular you have different options. Using Angular Elements is one of them. In this lesson we learn how to integrate an Angular Element into an AngularJS (v1.x) application. We will leverage some features release in the latest AngularJS 1.7.3 that make it fully compatible with custom elements.

Instructor: [00:00] When it comes to migrating your AngularJS app to Angular, you have different kind of options. One of them is basically to wrap your Angular components into Angular elements, to compile them, and then to include them into your legacy AngularJS applications.

[00:14] Let's take a look how we can create such an Angular element, and embed it into an AngularJS application. In my current setup here, I have already an AngularJS application running. You can see here the app is very simple.

[00:28] We have an AngularJS module. I use an AngularJS component. I write out some template, and then I bootstrap the app. You can see the result just right here in the output of the web browser. I already have also an Angular element here in place.

[00:42] It's a very simple feedback form which uses the material form field, and we have some inputs and some outputs, to which we would like to bind in our AngularJS application. The build process is already set up. We have here our build.wc as a script, which uses the Angular CLI, and builds everything into a single demo folder and the elements.js app.

[01:06] Again, if we jump there in that demo folder, we see the output here, which is our JavaScript file containing our Angular element, and also some styles to make them look pretty. The first step is to go to our AngularJS app.

[01:20] Let's create here a folder. Let's call it assets, and let's copy over basically output of our Angular element to the JavaScript files, as well as the styles, down to that asset folder. Next, we go into the index.html file here on our AngularJS app.

[01:39] Let's include here basically the CSS for our web component. These will be the styles. Then let's also here load already the script for our custom element, so that ngElement JavaScript file. From that point of view, we should already be set up.

[01:57] Next, what we obviously want to do is to include it in our AngularJS app. We go inside here, and use our feedback form tag, which instantiates now our Angular element. Let's refresh the browser here. You can see already that the form gets rendered nicely. We also have all the animations from Angular Material, and can use them in our AngularJS app.

[02:20] Next, of course, we want to bind to the output event from our Angular element. If we go to our feedback component TS file, we can see here we have that feedback submit. What's really cool about AngularJS is that the team made a really good effort to make it fully compatible with custom elements.

[02:38] The latest version, starting from 1.7.3, we can do a fully declarative registration of an event, a custom event that comes from an element. The only thing we needed to pay attention is we cannot write it like feedback submit, but rather we have to basically use the underscore.

[02:55] We can use that ngOn, and then the feedback name adjusts with that underscore, based on whether you have it camelcased or not. Then we use the usual controller mechanism as your custom on AngularJS.

[03:08] Let's call here some function and pass in the event object. Now, that function needs also obviously to be declared. Let's quickly do that. We will get here an event object. Let's just write it out to the console. Again, the detail here will contain now the output object that comes from our Angular component.

[03:31] If we save that, and we refresh our browser again, let's try it, "Yuri here. Hi there." If I submit, you can see here we get the object from our Angular component sent over to our AngularJS app and printed out to the console.

[03:45] That was only half of the story, because obviously, what we also want to use to use .input to pre-initialize, for instance, our Angular component, to communicate inwards and not just outwards. Similarly, to the ngOn event, the team also added an ngProp.

[04:01] We can use here the ngProp name, which would match here the name of our input property. In this case, we bind it to something that our controller might have. For instance, this.name equals Yuri. We could just do controller.name.

[04:15] If I save this again, if I refresh, you would actually expect it to be bound to our form, but it's not the case. The point here is that inside our feedback form, we initialize the form directly in the ngOnInit at the end of our Angular component.

[04:30] However, the name gets sent by AngularJS only later. What we need to do is we need to adjust our feedback form component slightly. One way is to do a setter here. We would get here the value. We can initialize some local name variable here, just to have it then also in our getter.

[04:51] Also, we also need to create that one. What I also do is I directly patch our feedback form. I directed this.feedbackForm.batchValueName equals the val. With that, we should be set up. Now, we obviously need to recompile our component.

[05:10] Then also, to copy it over to our AngularJS app. Now, if I refresh here, you can see that the value correctly gets initialized now. To recap what we have seen now here is, we have used properties such as ngPropName to bind values from AngularJS to Angular element, from AngularJS to Angular.

[05:30] We have also use here the ngOn to hook onto a custom event that gets fired by our Angular element. Then we have handled it with a proper handler in AngularJS.

Ilham Wahabi
Ilham Wahabi
~ 3 years ago

great course, I hope you could make more angular-side-things related course like this :)

Juri Strumpflohner
Juri Strumpflohnerinstructor
~ 3 years ago

@Ilham Glad you liked it. What type of topics would you like to see? #curious 😉

Alex Hubitski
Alex Hubitski
~ 3 years ago

Juri, the intro mentions a change detection quirks and workarounds (at 4:07). I can't find which video has it? I need to deal with the same issue.

Juri Strumpflohner
Juri Strumpflohnerinstructor
~ 3 years ago

@Alex Hey. Yes right. I had recorded the videos a while back when there was still Angular v6 & the course has been sitting for a while in the publish queue. Just before publishing, I updated some of the videos to Angular v7 so that you get the most fresh content possible 🙂.

That said, the workaround is no more needed. That was a bug in Angular Material and has been solved in version 7. If you're curious, I just removed an obsolete portion of the code I had still forgotten to remove today. Here's the diff.

Related to change detection. That's something I'd like to dive deeper in some upcoming videos. Usually change detection should be fine as is. However, especially if you build a component library that you'd like to expose as a reusable library of custom elements across other frameworks etc...then it's would be best to disable Zone.js entirely (which is responsible for automatic change detection), and rather handle CD by yourself.

Like

platformBrowserDynamic()
  .bootstrapModule(AppModule, { ngZone: 'noop' })
  .catch(err => console.log(err));

Then in your components and whenever CD is needed, you inject the ChangeDetectorRef and invoke its .detectChanges() function.

It is more difficult to handle and thus maybe not feasible for when you bundle an entire small app in an Angular Element. But if your goal is to provide a clean component lib, you might want to go that road 😉.

Hope this was helpful, have a nice weekend