An Introduction to Angular Components
"Dumb" component: reusable Toolbar
The messaging app needs more functionality in the toolbar. We'll be adding that functionality using a reusable chunk of html and reference it in our views. This eliminates the need to write duplicate code for every view.
First let's create a components directory and a new toolbar directory with a toolbar.component.html
file. Your directory structure should look like:
/src/components/toolbar/toolbar.component.html
Let's copy the inner html from our current toolbar and place it in our new toolbar.component.html
file.
<span flex></span>
<a md-icon-button mdTooltip="Help"><md-icon>help</md-icon></a>
Create toolbar.component.ts
with td-toolbar
selector and reference our toolbar.component.html
file
import { Component } from '@angular/core';
@Component({
selector: 'td-toolbar',
templateUrl: './toolbar.component.html',
})
export class ToolbarComponent {}
Let's import our toolbar component in app.module.ts
and test out the toolbar component in overview.component.html
import { ToolbarComponent} from './components/toolbar/toolbar.component';
Then we add it as a declaration of our module, this is so our module recognizes what td-toolbar
is
declarations: [
ToolbarComponent
]
Replace the toolbar <div>
and the icon / spacer span element inside it with our new <td-toolbar>
component:
<td-toolbar td-toolbar-content flex layout="row"></td-toolbar
We can now add to our toolbar.component.html
and test if it works in our other views. Let's add in another anchor with icon for a docs link:
<span flex></span>
<a md-icon-button mdTooltip="Docs"><md-icon>chrome_reader_mode</md-icon></a>
<a md-icon-button mdTooltip="Help"><md-icon>help</md-icon></a>
Then add our component to the systems.component.html
view. It'll be the first element in <td-layout-nav>
<td-layout-nav logo="assets:teradata" toolbarTitle="Quickstart">
<td-toolbar td-toolbar-content flex layout="row"></td-toolbar>
...
Our toolbar should have two icons on the right side now in both the overview and systems views.
Let's add one more thing to the component—a drop down menu for user profile and settings. In toolbar.component.html, add a <span> element with a <button> for an <md-icon> with a <md-menu>. See the Covalent docs on angular material menus: https://teradata.github.io/covalent/\#/components/material-components
<span flex></span>
<a md-icon-button mdTooltip="Docs"><md-icon>chrome_reader_mode</md-icon></a>
<a md-icon-button mdTooltip="Help"><md-icon>help</md-icon></a>
<span>
<button md-icon-button [md-menu-trigger-for]="menu">
<md-icon>more_vert</md-icon>
</button>
<md-menu x-position="before" #menu="mdMenu">
<a md-menu-item><md-icon>person</md-icon>Profile</a>
<a md-menu-item><md-icon>settings</md-icon>Settings</a>
</md-menu>
</span>
Smart Component: reusable information messaging component
Our messaging app needs a new pattern for surfacing important information to users. We'll build a standard container with common elements that we can configure on the fly depending on different scenarios.
This time let's use the Angular CLI to quickly stub out our component with a single command.
On the command line type:
ng generate component components/info
That will create all the files you need:
In src/app/components/info/info.component.ts
, change the selector to td-info
:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'td-info',
templateUrl: './info.component.html',
styleUrls: ['./info.component.scss']
})
export class InfoComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
Like our toolbar component before, let's make this a "dumb" component first, then we'll make it smart.
<md-card>
<md-toolbar>
<span class="td-info-icon">
<md-icon>info_outline</md-icon>
</span>
<span>New tagging feature</span>
<span flex></span>
<a md-raised-button color="accent" routerLink="systems">
<span>Learn more</span>
</a>
</md-toolbar>
<md-card-content>
<p class="md-body-1">Learn about our new tagging feature that lets you tag and group your messages.</p>
</md-card-content>
<md-divider></md-divider>
<md-card-actions>
<a md-button href="http://google.com">
<span>See docs</span>
</a>
</md-card-actions>
</md-card>
Now we'll write a bit of css to info.component.scss
for icon spacing and then use our new info component in overview component view.
.td-info-icon {
margin: 0 14px;
line-height: 15px;
}
...
<div flex-gt-xs="40">
<td-info></td-info>
<md-card>
...
Now we can start adding in property bindings with @Input
import { Component, Input } from '@angular/core';
@Component({
selector: 'td-info',
templateUrl: './info.component.html',
styleUrls: ['./info.component.scss']
})
export class InfoComponent {
@Input() infoTitle: string;
}
We're adding @Input() infoTitle: string;
as a property binding so that we can dynamically change what the title of the info message is.
...
<span *ngIf="infoTitle">{{infoTitle}}</span>
...
Let's add that property to the markup in our view:
<td-info infoTitle="New tagging feature"></td-info>
Now we can add these property bindings to routerLinks, colors, text, and icons.
import { Component, Input } from '@angular/core';
@Component({
selector: 'td-info',
templateUrl: './info.component.html',
styleUrls: ['./info.component.scss']
})
export class InfoComponent {
/**
* infoTitle: string
*
* The title set in toolbar.
*/
@Input() infoTitle: string;
/**
* icon: string
*
* The icon name to be displayed before the title.
* Defaults to info_outline icon
*/
@Input() icon: string = 'info_outline';
/**
* iconColor?: string
*
* The optioinal icon color to be displayed before the title.
*/
@Input() iconColor: string;
/**
* info?: string
*
* The optional string content of the info body.
*/
@Input() info: string;
/**
* actionPrimary?: string
*
* The optional route for primary action button.
*/
@Input() actionPrimary: string;
/**
* actionPrimaryText?: string
*
* The optional text for primary action button.
*/
@Input() actionPrimaryText: string;
/**
* actionPrimaryColor?: string
*
* The optional background color for primary action button.
*/
@Input() actionPrimaryColor: string;
}
<md-card>
<md-toolbar>
<span class="td-info-icon" *ngIf="icon">
<md-icon ngClass="{{iconColor}}">{{icon}}</md-icon>
</span>
<span *ngIf="infoTitle">{{infoTitle}}</span>
<span flex></span>
<a md-raised-button color="{{actionPrimaryColor}}" *ngIf="actionPrimary && actionPrimaryText" [routerLink]="actionPrimary">
<span>{{actionPrimaryText}}</span>
</a>
</md-toolbar>
<md-card-content>
<p class="md-body-1" *ngIf="info">{{info}}</p>
</md-card-content>
<md-divider></md-divider>
<md-card-actions>
<a md-button href="http://google.com">
<span>See docs</span>
</a>
</md-card-actions>
</md-card>
<td-info
infoTitle="New tagging feature"
iconColor="tc-blue-500"
info="Learn about our new tagging feature that lets you tag and group your messages."
actionPrimary="systems"
actionPrimaryText="Read More"
actionPrimaryColor="accent">
</td-info>