Angular @Input and @Output Example

By Arvind Rai, February 11, 2024
This page will walk through Angular @Input and @Output example. The @Input is a decorator to mark an input property. The @Output is a decorator to mark an output property. The @Input is used to define an input property to achieve component property binding. The @Output is used to define output property to achieve custom event binding. The @Input and @Output can define alias for property names as @Input(alias) and @Output(alias).
Here on this page we will provide a complete example for @Input and @Output decorators. We are creating a parent component and two child components. We will perform component property binding and custom event binding using both the child components. In our example we will use @Input with different data types such as string, number, array and user defined class. The @Output will be used with the instance of EventEmitter. Now find the complete example step-by-step.

@Input

The @Input decorator binds a property within one component (child component) to receive a value from another component (parent component). This is one-way communication from parent-to-child. The component property should be annotated with @Input decorator to act as input property. A component can send a value to another component using component property binding and that component receives that value using @Input property.
Here we will learn how to use @Input decorator. It can be annotated at any type of property such as number, string, array or user defined class. To use alias for the binding property name we need to assign an alias name as @Input(alias).
Find the use of @Input decorator with string data type.
@Input() 
ctMsg : string;  
Now find array data type with @Input decorator. Here we are aliasing the property name. In the component property binding, alias name ctArray is used.
@Input('ctArray')
myctArray : Array<string>;  
Now find @Input decorator with a property of user defined class type.
@Input('stdLeader')
myStdLeader : Student;	 

@Output

The @Output decorator binds a property of a component to send data from one component (child component) to calling component (parent component). The @Output binds a property of the type of angular EventEmitter class. This property name will be a custom event name for calling component. The @Output decorator can also alias the property name as @Output(alias) and now this alias name will be used in custom event binding in calling component.
Find the @Output decorator using aliasing.
@Output('addStudentEvent') 
addStdEvent = new EventEmitter<Student>(); 
In the above code snippet, addStudentEvent is custom event name.
Find @Output decorator without aliasing.
@Output() 
sendMsgEvent = new EventEmitter<string>(); 
Here sendMsgEvent is custom event name.

Aliasing Input and Output properties

The @Input and @Output decorate input and output properties. The @Input can alias input property name and @Output can alias output property name.
1. Aliasing input property using @Input
To alias input property use an alias as @Input(alias). Find code snippet.
<child-two [stdLeader] = "stdLeaderObj"> </child-two> 
Here we are using property binding. The stdLeaderObj is the property of parent component. The stdLeader is the alias of child component property. Now find the below code snippet.
@Input('stdLeader')
myStdLeader : Student;	 
We learn that stdLeader is the alias of myStdLeader property.
2. Aliasing output property using @Output
To alias output property, use alias as @Output(alias).
Find the custom event binding as below.
<child-two (addNumberEvent) = "printSum($event)" > </child-two>  
Here addNumberEvent is a custom event name. When this event invokes, printSum() method is executed. Now find the code snippet.
@Output('addNumberEvent') 
addNumEvent = new EventEmitter<number>();	 
We learn here that addNumberEvent is the alias of addNumEvent.

Component Property Binding using @Input

Find the steps for component property binding using @Input decorator step-by-step.
1. In the parent component, first create a property. Here we are creating a property of our Student class type.
stdLeaderObj = new Student('Narendra', 'Modi');  
2. Create a custom element in parent component that is a selector of one of our child component. Here we will perform component property binding.
<child-two [stdLeader] = "stdLeaderObj"> </child-two>  
3. Use @Input decorator to declare child component property as an input property that will receive value from parent using component property binding. Here we are using aliasing for property name.
@Input('stdLeader')
myStdLeader : Student;	 
4. Now we are ready to fetch values from input component property in our child component.
{{myStdLeader.fname +' '+ myStdLeader.lname}}  

Custom Event Binding using @Output and EventEmitter

Here we will discuss custom event binding using @Output decorator step-by-step.
1. Create text box using element property binding in child component. The input event is fired when there is any change in text box. The $event.target.value fetches the current value of text box entered by user.
<div>
   First Number :<input (input)="num1=$event.target.value" /> <br/>
   Second Number:<input (input)="num2=$event.target.value" /> <br/>
  <br/> <button (click)="addNumber()">Add Number</button>
</div>	 
2. Find the method created in child component that will be fired when click event is invoked on click of button from above (step-1) code snippet. emit() is the method of EventEmitter class that emits event payload.
addNumber() {
    this.addNumEvent.emit(parseInt(this.num1) + parseInt(this.num2));
}	 
3. In the child component, create an instance of EventEmitter annotated by @Output decorator. This instance will work as custom event name. Here we are using aliasing for custom event name.
@Output('addNumberEvent') 
addNumEvent = new EventEmitter<number>();  
4. Now we are performing custom event binding. The custom event addNumberEvent will be invoked in parent component when emit() method is invoked from child component. The event payload is accessed by $event object.
<child-two (addNumberEvent) = "printSum($event)" > </child-two>  
5. The event addNumberEvent will call printSum() method.
printSum(res) {
    this.sum = res;
}	 


Complete Example

We will provide a complete example of @Input and @Output decorator using TypeScript. In our example we will create a parent component and two child component. Both child will use @Input and @Output decorator.
student.ts
export class Student {
   constructor(public fname?: string, public lname?: string) { 
   }
} 
In the above code we will observe that we are using question mark ? in constructor parameter. By using question mark ? in constructor parameter, we achieve that while creating instance of Student class, passing arguments are optional. And it is possible to create instance of our Student class as new Student() without passing any argument. If we do not use question mark ? in constructor parameters, new Student() will through error and requires arguments.
parent.component.ts
import { Component } from '@angular/core';
import { Student } from './student';
@Component({
	selector: 'app-root',
	template: `
	                        <h1>{{parentTitle}}</h1>
				<child-one
					[ctMsg]="cityMsg" 				
					[ctArray]="cityArray"	
					[studentAddMsg]="stdAddMsg" 						
				    (addStudentEvent) = "saveData($event)"
					(sendMsgEvent) = "printMsg($event)"	>
				</child-one>
				<p>Name: {{stdFullName}}</p>				
				<p>Message: {{msg}}</p>	
				<child-two
					[studentMsg] = "stdMsg"				
					[stdLeader] = "stdLeaderObj" 
					(addNumberEvent) = "printSum($event)" >
				</child-two>
				<p>Sum: {{sum}}</p>							
	          `
})
export class ParentComponent {
	parentTitle = 'Parent Component';

	//Property for child component one
	cityMsg = 'Indian City Names';
	cityArray = ['Varanasi', 'Delhi', 'Mumbai'];
	stdAddMsg = 'Add Student';

	//Property for child component two
	stdMsg = 'Student Leader Detail';
	stdLeaderObj = new Student('Narendra', 'Modi');

	//Property used in parent
	stdFullName = '';
	sum = '';
	msg = '';

	saveData(std: Student) {
		this.stdFullName = std.fname + ' ' + std.lname;
	}
	printSum(res: any) {
		this.sum = res;
	}
	printMsg(msg: string) {
		this.msg = msg;
	}
} 
childone.component.ts
import {Component, EventEmitter, Input, Output} from '@angular/core';
import {Student} from './student';
@Component({
    selector: 'child-one',
    template: `
	                        <h3>{{childTitle}}</h3>
	                        <b> {{ctMsg}}</b>
				<ul>
				 <li *ngFor = "let cname of myctArray">
				    {{cname}}
				 </li>
				</ul>
				
			        <b>{{addMsg}}</b><br/>
				<div>
					First Name:<input (input)="student.fname=getVal($event.target)" /> <br/>
					Last Name:<input (input)="student.lname=getVal($event.target)" />
					<br/> <button (click)="addStudent()">Add Student</button>
				</div>
				
				<br/><b>{{message}}</b><br/>
				<div>
					Message :<input (input)="msg=getVal($event.target)" />
					<br/> <button (click)="sendMsg()">Send</button>
				</div>		
			 `
})
export class ChildOneComponent {

	@Input() 
	ctMsg : string = ''; 
	
	@Input('ctArray')
	myctArray = {} as Array<string>;

        @Input('studentAddMsg') 
	addMsg : string = ''; 	
	
  	@Output('addStudentEvent') 
	addStdEvent = new EventEmitter<Student>();

  	@Output() 
	sendMsgEvent = new EventEmitter<string>();	
	
	student = new Student('', '');
	childTitle = '---Child One---';
	message = 'Send Message'
	msg = '';
	
	addStudent() {
	      this.addStdEvent.emit(this.student);
        }	
	sendMsg() {
	      this.sendMsgEvent.emit(this.msg);
        }	
	getVal(ob: EventTarget | null) {
              return (<HTMLInputElement>ob).value;
	}
} 
childtwo.component.ts
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Student } from './student';
@Component({
	selector: 'child-two',
	template: `
	                        <h3>{{childTitle}}</h3>
				<p> {{studentMsg}} : {{myStdLeader.fname +' '+ myStdLeader.lname}}  </p>

				<b>{{addNumMsg}}</b><br/>
				<div>
					First Number :<input (input)="num1=getVal($event.target)" /> <br/>
					Second Number:<input (input)="num2=getVal($event.target)" /> <br/>
					<br/> <button (click)="addNumber()">Add Number</button>
				</div>		
			  `
})
export class ChildTwoComponent {
	@Input()
	studentMsg: string = '';

	@Input('stdLeader')
	myStdLeader = {} as Student;

	@Output('addNumberEvent')
	addNumEvent = new EventEmitter<number>();

	childTitle = '---Child Two---';
	addNumMsg = 'Add Number'
	num1 = '';
	num2 = '';

	addNumber() {
		this.addNumEvent.emit(parseInt(this.num1) + parseInt(this.num2));
	}
	getVal(ob: EventTarget | null) {
		return (<HTMLInputElement>ob).value;
	}
} 
app.module.ts
import {NgModule}           from '@angular/core';
import {BrowserModule}      from '@angular/platform-browser';
import {ParentComponent}    from './parent.component';
import {ChildOneComponent}  from './childone.component';
import {ChildTwoComponent}  from './childtwo.component';
@NgModule({
  imports:      [BrowserModule],
  declarations: [ParentComponent, 
                 ChildOneComponent,
		 ChildTwoComponent],
  bootstrap:    [ParentComponent]
})
export class AppModule { } 

Output

Find the print-screen of the output.
Angular @Input and @Output Example

References

Input Decorator
Output Decorator

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI







©2024 concretepage.com | Privacy Policy | Contact Us