Let's get to the point. Angular document gives me a basic understanding of each feature, but when it come to solving real world problem, I would be thinking of how do they work together?.
I've written one example to demonstrate just that.
Problem Scenario
In one course, I have to learn two subjects. Angular and Code Sandbox. In Angular subject I have two tasks which give me two credit. Code sandbox has one task with one credit.
To complete the course, I need to gain three credits.
Now I need to write an application to track my progress.
Big Picture
+--------------------+ | Subjects | : Keeping record of credits | +--------------+ | | | Tasks | | : To do list, tick off done tasks | | +---------+ | | | | | Report | | | : Keeping record of task completed | | +---------+ | | | +--------------+ | +--------------------+
Abstract Steps
- Initialise Default Angular Project
- Create three components (subjects, tasks, report)
- Replace content of
app.comopnent.html
withsubjects
component - Add functions
Codes
This diagram let you visualise where @Input
, @Output
and EventEmitter
is used
+----------+ Data Flow +-----------+ | Tasks + ----------> + Subjects | +----------+ +-----------+ @Output():EventEmitter +----------+ Data Flow +----------+ | Tasks + ----------> + Report | +----------+ +----------+ @Input():number
Subject Component
<section id="subjects"> <h4>Subjects</h4> <div *ngFor="let subject of subjects"> <div>{{subject.desc}} - Credit: {{subject.credit}}</div> </div> <app-task (subjectCompleteEvent)="receiveSubjectCompletion($event)" ></app-task> </section>
import { Component, OnInit } from "@angular/core"; @Component({ selector: "app-subject", templateUrl: "./subject.component.html" }) export class SubjectComponent implements OnInit { subjects: any[] = []; ngOnInit(): void { this.subjects.push({ code: "ng", desc: "Angular", credit: 0 }); this.subjects.push({ code: "sb", desc: "Code Sanbox", credit: 0 }); } receiveSubjectCompletion(subjectComplete: any) { const index = this.subjects .map((subject) => { return subject.code; }) .indexOf(subjectComplete.code); subjectComplete.credit ? this.subjects[index].credit++ : this.subjects[index].credit--; } }
Tasks Component
<section id="tasks"> <h4>Tasks</h4> <div *ngFor="let task of todos"> <input type="checkbox" (change)="onCheck($event)" value="{{task.code}}" />{{task.desc}} </div> <app-report [completed]="taskCompleteCounts"></app-report> </section>
import { Component, OnInit, Output, EventEmitter } from "@angular/core"; @Component({ selector: "app-task", templateUrl: "./task.component.html" }) export class TaskComponent implements OnInit { // define output type for notifying parent component @Output() subjectCompleteEvent: EventEmitter<any> = new EventEmitter<any>(); // input value for report (child) taskCompleteCounts = 0; todos: any[] = []; ngOnInit(): void { this.todos.push({ code: "ng", desc: "Scaffold Angular Project" }); this.todos.push({ code: "ng", desc: "Try EventEmitter, @Input, @Output" }); this.todos.push({ code: "sb", desc: "Try Code Sandbox" }); } onCheck(event: any) { if (event.target.checked) { // update value for child this.taskCompleteCounts++; // notify parent this.subjectCompleteEvent.emit({ code: event.target.value, credit: true }); } else { this.taskCompleteCounts--; this.subjectCompleteEvent.emit({ code: event.target.value, credit: false }); } } }
Report Component
<section id="report"> <h4>Report</h4> <div> Task completed: {{completed}} </div> </section>
import { Component, OnInit, Input } from "@angular/core"; @Component({ selector: "app-report", templateUrl: "./report.component.html" }) export class ReportComponent implements OnInit { // define input type. value will be updated from parent @Input() completed: number; ngOnInit(): void {} }
Demo
https://codesandbox.io/s/ng-eventemitter-input-output-57r1z
It's freedom to use this content under CC-BY-4.0, program codes under CC0 licence.
Top comments (0)