Angular is a popular front-end framework made by Google. Like other popular front-end frameworks, it uses a component-based architecture to structure apps.
In this article, we’ll look at the NgSwitch
directive, template variables, and Input
and Ouput
syntax.
The NgSwitch
directives
We can use the NgSwitch
directive to display an item from a list of possible choices.
For example, we can use it as follows:
app.component.ts
:
import { Component } from "@angular/core";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
name = "foo";
}
app.component.html
:
<div [ngSwitch]="name">
<p *ngSwitchCase="'foo'">foo</p>
<p *ngSwitchCase="'bar'">bar</p>
<p *ngSwitchCase="'baz'">baz</p>
</div>
In the code above, we have the name
field in AppComponent
set to 'foo'
.
Then in app.component.html
, we have ngSwitch
set to name
so that it checks the value of name
in AppComponent
to get what to display.
We have multiple *ngSwitchCase
with different values so that if name
is 'foo'
, we display ‘foo’, if name
is 'bar'
then we display ‘bar’, and if name
is 'baz'
, we display ‘baz’.
Since name
is ‘foo’
, we display ‘foo’.
*ngSwitchCase
works with both native elements and components.
Template Reference Variables (#var)
A template reference variable is often a reference to a DOM element within a template. It can also refer to a directive, an element. TemplateRef
or a web component.
For example, we can use it as follows:
app.component.ts
:
import { Component } from "@angular/core";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
call(phone) {
alert(`Calling ${phone.value}`);
}
}
app.component.html
:
<input #phone placeholder="phone" />
<button (click)="call(phone)">Call</button>
In the code above, we added a call
method which takes in the phone
element as the argument and shows an alert with the value typed into the phone
input.
Then we added #phone
in app.component.html
to reference the input element. Also, we added a button to call the call
method with the phone
input reference so that we can show the value in the alert.
NgForm
The NgForm
directive change behavior and set the value of the template variable to something else.
With it, we can reference the form with a variable inside our outside the form.
For example, we can use NgForm
as follows:
app.component.ts
:
import { Component } from "@angular/core";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
onSubmit(itemForm) {
if (itemForm.invalid) {
return;
}
alert("form submitted");
}
}
app.component.html
:
<form #itemForm="ngForm" (ngSubmit)="onSubmit(itemForm)">
<label>Name <input name="name" ngModel required /> </label>
<button type="submit">Submit</button>
</form>
<div [hidden]="itemForm.form.valid">
<p>Missing name</p>
</div>
In the code above, we have the onSubmit
method in AppComponent
, which takes the itemForm
reference. Then we can use it to check for validity in the component before submitting.
Then in app.component.html
, we created the #itemForm
variable by using the ngForm
directive so that we can reference the form and check its validity in the bottom div
and in onSubmit
with itemForm
passed in.
Alternative Syntax
We can use the ref-
prefix instead of #
, so we can write:
<input ref-phone placeholder="phone" />
<button (click)="call(phone)">Call</button>
@Input()
and @Output()
Properties
@Input
and @Output
allow Angular to share data between the parent context and child directives and components.
How to use @Input()
For example, we can write the following to use @Input
to pass in data from the parent component to the child:
app.module.ts
:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { PersonComponent } from './person/person.component';
@NgModule({
declarations: [
AppComponent,
PersonComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts
:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
persons = [{ name: 'Jane' }, { name: 'John' }, { name: 'Mary' }];
}
app.component.html
:
<app-person *ngFor="let p of persons" [person]='p'></app-person>
person.component.ts
:
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-person',
templateUrl: './person.component.html',
styleUrls: ['./person.component.css']
})
export class PersonComponent {
@Input() person;
}
person.component.html
:
<div>{{person.name}}</div>
In the code above, we created a PersonComponent
component and then included it in the declarations
array of AppModule
.
Then in AppComponent
, we have:
persons = [{ name: 'Jane' }, { name: 'John' }, { name: 'Mary' }];
and *ngFor
in app.component.html
to loop through the items and render the PersonComponent
.
We pass in p
as the value of the person
property and then it’ll be the value of person
in the PersonComponent
.
Finally, we display the name
value of person
in person.component.html
.
In the end, we should see:
JaneJohnMary
displayed on the screen.
How to use @Output()
We can use the @Output
decorator in the child component or directive to pass data from child to parent.
For example, we can use it as follows:
app.module.ts
:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { PersonComponent } from './person/person.component';
@NgModule({
declarations: [
AppComponent,
PersonComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts
:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
emittedName: string;
}
app.component.html
:
<app-person (name)='emittedName = $event'></app-person>
<p>{{emittedName}}</p>
person.component.ts
:
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-person',
templateUrl: './person.component.html',
styleUrls: ['./person.component.css']
})
export class PersonComponent {
@Output() name = new EventEmitter<string>();
emitName() {
this.name.emit('Jane');
}
}
person.component.html
:
<button (click)='emitName()'>Get Name</button>
In the code above, we have the button in person.component.html
which calls the PersonComponent
’s emitName
method to emit the string 'Jane'
to the parent component with the EventEmitter
.
Then in the parent component, AppComponent
, we have:
<app-person (name)='emittedName = $event'></app-person>
in app.component.html
.
$event
has the value emitted from the name
emitter. Then we set it to emittedName
and displayed it.
@Input() and @Output() together
We can use them together.
For example, we can write:
<app-input-output [item]="currentItem" (deleteRequest)="deleteItem($event)"></app-input-output>
In the code above, we pass currentItem
to the item
property to the app-input-output
component.
The deleteRequest
is emitted from app-input-output
and then the deleteItem
method is called with what’s passed from the child when deleteRequest
is emitted.
We can pass in a name to Input
and Output
to change the name of them respective and then we can reference them with that name in our templates.
Conclusion
We can use NgSwitch
to display an item depending on value of something in the component.
Template variables let us reference DOM elements in our templates and access its properties.
With Input
and Output
, we can pass data to a child component or directive and pass items from child to parent respectively.