Categories
Angular JavaScript

Angular Directives — NgSwitch, Input, and Output

Spread the love

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.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *