Build A Container Component in Angular 2

Build A Container Component in Angular 2

  • 2016-10-13
  • 1133

Angular 2: How To Build A Container Component

Previously on Angular 2: The Future of JavaScript is Now I talked about all the cool features announced at the #ngConf2016. This time I have decided to start working in a new project in Angular 2 by using only the tools provided by the Angular 2 Ecosystem.

Each part of this project will help me to create more tutorials like this.

Project Description

I have been working with Angular 2 for 3 projects by now and something I have regullary seen is that we will need to create container components, basically everytime we build an application based on web components.

In this tutorial we are going to create an Angular 2 Container Component, this kind of components won’t render content but provides tools for developers to create different type of structures.

Example of Implementation

The container component we are going to create is going to help developers create grid structures, but if you have used Ionic or Angular Material you should be familiar with these type of structures.

<grid>
  <grid-title>LATEST TUTORIALS</grid-title>
  <grid-row>
    <grid-item>
    </grid-item>
  </grid-row>
</grid>

Code Repo

NG2 Grid

Requirements

Install the Angular CLI.

$ npm install -g angular-cli

Create Project

Once we have the Angular CLI installed, we can create a new Angular 2 project named container.

$ ng new container --prefix ''

It will take some time until everything is installed, I added the --prefix '' parameter because otherwise angular will append by default the app- prefix to any of our generated components.

For demo purposes it seems dirty if I leave the default prefix… But in real life, you will be adding your company or personal prefix as namespace of the component selector.

Then you can verify your app by running:

$ cd container
$ ng serve

If you open a browser and use the http://localhost:4200 path, you will be able to see a “Container Works!” message.

Create Grid Component

Now lets stop the server a moment and create our GridComponent using the Angular CLI‘s command ng generate

$ ng generate component grid
Visit http://ember-cli.com/user-guide/#watchman for more info.
installing component
  create src/app/grid/grid.component.css
  create src/app/grid/grid.component.html
  create src/app/grid/grid.component.spec.ts
  create src/app/grid/grid.component.ts
  create src/app/grid/index.ts

As you can see the generator created a set of files that composes our basic structure for the grid component.

Define Grid Component View

We won’t add logic to our component because this is a basic container component, of course we could add some logic if we want to take this component beyond, but that can be for a future blog post.

For now we are going to focus on create a view structure, for this we are going to use the <ng-content></ng-content> directive.

<ng-content select="app-grid-title"></ng-content>
<ng-content></ng-content>

If you go back to the Example of Implementation you will see implemented the <grid-title></grid-title> selector, but we won’t actually create a directive or component for that, instead we use the select="" within our <ng-content></ng-content> and we can actually select the content within that html tag and interpolate within our grid component view.

So whatever the developer who uses this directive passes as content will be interpolated within this component.

Style Grid Component

For this component we are going to use a lot the help of Flex the CSS3’s amazing functionallity that goes really well with this example, so we will build a good and more modern replacement for the native table html component.

:host {
  display: flex;
  flex-direction: column;
  border: 1px solid #eee;
  border-right: 0px;
}

:host grid-title {
  display: flex;
  flex-direction: row;
  padding: 15px 10px;
  border-right: 1px solid #eee;
}

When we use the selector :host we refer to the host component instance scope we are located, this is how we can provide some styling to the root container.

Then we set the flex direction to column because we want to create some sort of list in which we later will add rows in order to create a grid view.

Generate Row and Item Components

$ ng generate component grid-row
$ ng generate component grid-item

Now since we want to bundled our component together we need to move all filex except index.ts the files created in src/app/grid-item and src/app/grid-row to the src/app/grid, at the end we should have a structure like the follow:

+ src
| + app
| | + grid
| | | grid-item.component.css
| | | grid-item.component.html
| | | grid-item.component.ts
| | | grid-row.component.css
| | | grid-row.component.html
| | | grid-row.component.ts
| | | grid.component.css
| | | grid.component.html
| | | grid.component.ts
| | | index.ts

Something really important when we are shipping multiple directives within our component is to export a directives array within our index.ts.

import { GridComponent } from './grid.component';
import { GridRowComponent } from './grid-row.component';
import { GridItemComponent } from './grid-item.component';

export const GRID_DIRECTIVES = [
  GridComponent,
  GridRowComponent,
  GridItemComponent
];

You will see really ofen that you will be importing this form of components structure, so it makes life easier for the developers that will implement this code later on.

Important: since we created the row and item components using the generator, it configured for us the system-config.ts file in the app root, so we need to remove the following lines from the barrel section:

const barrels: string[] = [
  // Angular specific barrels.
  [email protected]/core',
  [email protected]/common',
  [email protected]/compiler',
  [email protected]/http',
  [email protected]/router',
  [email protected]/platform-browser',
  [email protected]/platform-browser-dynamic',

  // Thirdparty barrels.
  'rxjs',

  // App specific barrels.
  'app',
  'app/shared',
  'app/grid',
  'app/grid-row', // <--- Remove This
  'app/grid-item', // <--- And Remove This
  /** @cli-barrel */
];

Update Row and Item Views

For both components we are going to use again the <ng-content></ng-content> directive without any other type of configurations, just the following:

Files: grid-row.component.html and grid-item.component.html

<ng-content></ng-content>

Update Row and Item Styles

File: grid-row.component.css

<ng-content></ng-content>

File: grid-item.component.css

:host {
  flex-grow: 1;
  padding: 10px;
  border: 1px solid #eee;
  border-left: 0px;
  border-bottom: 0px;
}

Implementation in ContainerAppComponent

Open the container.component.ts file and update as follows:

import { Component } from [email protected]/core';
import { GRID_DIRECTIVES } from './grid';

@Component({
  moduleId: module.id,
  selector: 'container-app',
  templateUrl: 'container.component.html',
  styleUrls: ['container.component.css'],
  directives: [...GRID_DIRECTIVES]
})
export class ContainerAppComponent {
  title = 'container works!';
}

Remember the GRID_DIRECTIVES? well as you can see by implementing this in to the main component is much more easier than importing all of them and set each of these within the directives array section.

Implementation in ContainerAppComponent View

<h1>
  {{title}}
</h1>
<grid>
  <grid-title>Grid Title</grid-title>
  <grid-row>
    <grid-item>
      A
    </grid-item>
    <grid-item>
      B
    </grid-item>
    <grid-item>
      C
    </grid-item>
  </grid-row>
  <grid-row>
    <grid-item>
      E
    </grid-item>
    <grid-item>
      D
    </grid-item>
  </grid-row>
  <grid-row>
    <grid-item>
      F
    </grid-item>
  </grid-row>
</grid>

Test

Now if you start the server again by running

$ ng serve

You should be able to see a grid component with title, rows and items adjusted pretty neat because of the use of flex.

Suggest

Learn and Understand AngularJS & Angular 2

Angular 2 From The Ground Up - Early Access

Build A Web App With Spring Framework and Angular 2

Learn By Example: Angular JS

Angular 2 Concepts, Code and Collective Wisdom

Angular 2 Fundamentals: Learn By Creating A Real Web App