We are following the development of Angular 2.0.0 since the beginning on and are also contributing to the project. Just recently we’ve built a simple zippy component in Angular and in this article we want to show you how.
Want to see things in action first?
TABLE OF CONTENTS
Getting started with Angular 2.0.0
There are several options today to get started with Angular. For instance, we can go to angular.io and use the quickstart guide. Or, we can install the Angular CLI, which takes care of scaffolding, building and serving Angular applications. In this article we will use
Pawel Kozlowski's ng2-play repository the Angular CLI, but again, you can use whatever suits you.
We start by installing Angular CLI as a global command on our local machine using npm.
Once that is done, we can scaffold a new Angular project by running
ng new <PROJECT_NAME>. Note that the project is scaffolded in the directory where we’re in at this moment.
Next, we navigate into the project and run
ng serve, which will essentially build and serve a hello world app on
We open a browser tab on
localhost://4200 and what we see is the text “zippy-app works!”. Cool, we’re all set up to build a zippy component in Angular!
Building the zippy component
Before we start building the zippy component with Angular, we need to clarify what we’re talking about when using the term “zippy”. It turns out that a lot of people think they don’t know what a zippy is, even if they do, just because of the naming.
Long story short: this, is a zippy.
Also known as “accordion”. You can click the summary text and the actual content toggles accordingly. If you take a look at this particular plunk, you’ll see that we actually don’t need to do any special implementation to get this working. We have the
<details> element that does the job for us. But how can we implement such a thing in Angular?
We start off by adding a new file
src/app/my-zippy.component.ts and creating a class in ES2015 that we export, so it can be imported by other consumers of this class, by using the ES2015 module system. If you’re not familiar with modules in ES2015 you might want to read our article on using ES2015 with Angular today.
Special Tip: We would normaly use Angular CLI to generate a component for us, instead of creating the files manually, but this articles focuses on understanding the building blocks of creating a custom component.
The next thing we want to do, is to make our
ZippyComponent class an actual component and give it a template so that we can see that it is ready to be used. In order to tell Angular that this particular class is a component, we use something called “Decorators”.
Decorators are a way to add metadata to our existing code. Those decorators are actually not supported by ES2015 but have been developed as language extension of the TypeScript transpiler, which is used in this project. We’re not required to use decorators though. As mentioned, those are just transpiled to ES5 and then simply used by the framework. However, for simplicity sake we’ll use them in this article.
Angular provides us with a couple of decorators so we can express our code in a much more elegant way. In order to build a component, we need the
@Component() decorator. Decorators can be imported just like classes or other symbols, by using ES2015 module syntax. If you heard about annotations in traceur before and wonder how they relate to decorators, you might want to read our article on the difference between annotations and decorators.
Component decorator adds information about what our component’s element name will be, what input properties it has and more. We can also add information about the component’s view and template.
We want our zippy component to be usable as
<my-zippy> element. So all we need to do, is to add a
@Component() decorator with that particular information. To specify the element name, or rather CSS selector, we need to add a
selector property that matches a CSS selector.
Next, our component needs a template. We add information about the component’s view.
templateUrl tells Angular where to load the component template from. To make
templateUrl work with relative paths, we add another property
moduleId with a value
module.id. To get more information on
moduleId, make sure to check out our article on Component-Relative Paths in Angular
Later at runtime, when Angular compiles this component, it’ll fetch
my-zippy.component.html asynchronously. Let’s create a file
src/app/my-zippy.component.html with the following contents:
CSS classes can be ignored for now. They just give us some semantics throughout our template.
Alright, believe it or not, that’s basically all we need to do to create a component. Let’s use our zippy component inside the application. In order to do that, we need to do things:
- Add our new component to the application module
Angular comes with a module system that allows us to register directives, components, service and many other things in a single place, so we can use them throughout our application. If we take a look at the
src/app/app.module.ts file, we see that Angular CLI already created a module for us. To register
AppModule, we import it and add it to the list
We don’t worry too much about the
imports for now, but we acknowledge that Angular needs
BrowserModule to make our app run in the browser. The
declarations property defines all directives and pipes that are used in this module and
bootstrap tells Angular, which component should be bootstrapped to run the application.
ZippyAppComponent is our root component and has been generated by Angular CLI as well,
ZippyComponent is our own custom component that we’ve just created.
Now, to actually render our zippy component in our application, we need to use it in
ZippyAppComponent’s template. Let’s do that right away:
Nice! Running this in the browser gives us at least something that looks like a zippy component. The next step is to bring our component to life.
Bringing the component to life
In order to bring this component to life, let’s recap quickly what we need:
- Clicking on the zippy title should toggle the content
- The title of the should be configurable from the outside world, currently hard-coded in the template
- DOM that is used inside the
<my-zippy>element should be projected in the zippy content
Let’s start with the first one: when clicking on the zippy title, the content should toggle. How do we implement that in Angular?
We know, in Angular 1.x, we’d probably add an
ngClick directive to the title and set a scope property to
false and toggle the zippy content respectively by using either
ngShow. We can do pretty much the same in Angular >= 2.x as well, just that we have a bit different semantics.
Instead of adding an
ngClick directive (which we don’t have in Angular 2.x), to call for instance a method
toggle(), we bind to the
click event directly using the following template syntax.
If you’re not familiar with this syntax I recommend you either reading this article on integrating Web Components with Angular, or this article about Angular’s template syntax demystified. Misko’s keynote from this year’s ng-conf is also a nice resource.
Now we’re basically listening on a
click event and execute a statement. But where does
toggle() come from? We can access component methods directly in our template. There’s no
$scope service or controller that provides those methods. Which means,
toggle() is just a method defined in
Here’s what the implementation of this method could look like:
We simply invert the value of the component’s
visible property. In order to get a decent default state, we set
true when the component is loaded.
Now that we have a property that represents the visibility state of the content, we can use it in our template accordingly. Instead of
ngShow (which we also don’t have in Angular >= 2.x), we can simply bind the value of our
visible property to our zippy content’s
hidden property, which every DOM element has by default.
Again, what we see here is part of the new template syntax in Angular. Angular >= 2.x binds to properties rather than attributes in order to work with Web Components, and this is how you do it. We can now click on the zippy title and the content toggles!
Oh! The little arrow in the title still points down, even if the zippy is closed. We can fix that easily with Angular’s interpolation like this:
Okay, we’re almost there. Let’s make the zippy title configurable. We want that consumers of our component can define how they pass a title to it. Here’s what our consumer will be able to do:
In Angular >= 2.x, we don’t need to specify how scope properties are bound in our component, the consumer does. That means, this gets a lot easier in Angular too, because all we need to do is to import the
@Input() decorator and teach our component about an input property, like this:
Basically what we’re doing here, is telling Angular that the value of the
title attribute is projected to the
title property. Input data that flows into the component. If we want to map the
title property to a different attribute name, we can do so by passing the attribute name to
But for simplicity’s sake, we stick with the shorthand syntax. There’s nothing more to do to make the title configurable, let’s update the template for
Now we need to change the template of zippy to make title to appear at correct place, let’s udpate the template for zippy title.
Insertion Points instead of Transclusion
Our component’s title is configurable. But what we really want to enable, is that a consumer can decide what goes into the component and what not, right?
We could for example use our component like this:
In order to make this work, we’ve used transclusion in Angular 1. We don’t need transclusion anymore, since Angular 2.x makes use of Shadow DOM (Emulation) which is part of the Web Components specification. Shadow DOM comes with something called “Content Insertion Points” or “Content Projection”, which lets us specify, where DOM from the outside world is projected in the Shadow DOM or view of the component.
I know, it’s hard to believe, but all we need to do is adding a
<ng-content> tag to our component template.
Angular uses Shadow DOM (Emulation) since 2.x by default, so we can just take advantage of that technology.
It turns out that insertion points in Shadow DOM are even more powerful than transclusion in Angular. Angular 1.5 introduces multiple transclusion slots, so we can explicitly “pick” which DOM is going to be projected into our directive’s template. The
<ng-content> tag lets us define which DOM elements are projected too. If you want to learn more about Shadow DOM, I recommend the articles on html5rocks.com or watch this talk from ng-europe.
Putting it all together
Yay, this is how we build a zippy component in Angular. Just to make sure we’re on the same page, here’s the complete zippy component code we’ve written throughout this article:
And here’s the template:
I’ve set up a repository so you can play with the code here. In fact, I’ve also added this component to the Angular project. The pull request is
pending merged here and likely to be merged the next few days. At this point I’d like to say thank you to Victor and Misko for helping me out on getting this implemented.
You might notice that it also comes with e2e tests. The component itself even emits it’s own events using
EventEmitter, which we haven’t covered in this article. Check out the demos to see event emitters in action!
Angular Master Class at Shopware
Join our upcoming public training!Get a ticket →
Get updates on new articles and trainings.
Join over 1400 other developers who get our content first.
RxJS Master Class and courseware updates
If you've been following us for a while, you're quite aware that we're always striving to provide up-to-date and high-quality...
Advanced caching with RxJS
When building web applications, performance should always be a top priority. One very efficient way to optimize the performance of...
Custom Overlays with Angular's CDK - Part 2
In this follow-up post we demonstrate how to use Angular's CDK to build a custom overlay that looks and feels...
Custom Overlays with Angular's CDK
The Angular Material CDK provides us with tools to build awesome and high-quality Angular components without adopting the Material Design...
Easy Dialogs with Angular Material
Building modals and dialogs isn't easy - if we do it ourselves. Angular Material comes with a powerful dialog service...
A web animations deep dive with Angular
Angular comes with a built-in animation system that lets us create powerful animations based on the Web Animations API. In...