SlideShare a Scribd company logo
Component Communication
What is a component
@Component({
selector: 'myComp',
template: `
<div>
Content: {{myVar}}
</div>
`
})
class MyComponent {
myVar: string;
constructor() {
this.myVar = 'hello';
}
}
Output
Input
<html>
<myComp></myComp>
</html>
<html>
<myComp>
<div>
Content: hello
</div>
</myComp>
</html>
Parent → Child
@Component({
selector: 'parent',
template: `
<div>
Parent content
<child [param]="myVar"></child>
Parent content
</div>
`
})
class ParentComponent {
myVar = 'hello';
}
@Component({
selector: 'child',
template: '<div>Child: {{param}}</div>'
})
class ChildComponent {
@Input() param: string;
}
<html>
<parent>
<div>
Parent content
<child>
Child hello
</child>
Parent content
</div>
</parent>
</html>
Output
Input
<html>
<parent></parent>
</html>
wizardComp
@Input() Demo
Child → Parent
@Component({
selector: 'parent',
template: `
<div>
<child (childEvent)="handelChildEvent($event)"></child>
</div>
`
})
class ParentComponent {
handelChildEvent(message) {
console.log(message);
}
}
@Component({
selector: 'child',
template: `
<button (click)="childEvent.emit('clicked')">Click me</button>
`
})
class ChildComponent {
@Output() childEvent = new EventEmitter();
}
@Output() Demo
Sibling → Sibling
@Component({
selector: 'sibling2',
template: `
<button (click)="myService.increment()">
Increment
</button>`
})
class Sibling2Component {
constructor(public myService: MyService) {
}
}
@Component({
selector: 'sibling1',
template: `{{myService.counter}}`
})
class Sibling1Component {
constructor(public myService: MyService) {
}
}
class MyService {
counter: number = 0;
increment() {
this.counter++;
}
}
Sibling Demo
user.service.ts
export class UserService {
users: User[] = [];
}
user.service.ts
export class UserService {
private users$ = new BehaviorSubject([]);
}
user.service.ts
export class UserService {
private users$ = new BehaviorSubject([]);
addUser(user) {
let users = [user, ...this.users$.getValue()];
this.users$.next(users);
}
}
user.service.ts
export class UserService {
private users$ = new BehaviorSubject([]);
addUser(user) {
let users = [user, ...this.users$.getValue()];
this.users$.next(users);
}
removeUser(user) {
let users = this.users$.getValue().filter(u => u !== user);
this.users$.next(users);
}
}
user.service.ts
export class UserService {
private users$ = new BehaviorSubject([]);
addUser(user) {
let users = [user, ...this.users$.getValue()];
this.users$.next(users);
}
removeUser(user) {
let users = this.users$.getValue().filter(u => u !== user);
this.users$.next(users);
}
getUsers() {
return this.users$.asObservable();
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `
<div *ngFor="let user of filteredUsers">
<input #firstName (keyup)="filterUsers(firstName.value)">
</div>
`
})
export class UserSearchComponent {
filteredUsers: User[];
constructor(public userService: UserService) {
}
filterUsers(search) {
this.filteredUsers = this.userService.users.filter(user =>
user.firstName.includes(search));
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `
<div *ngFor="let user of filteredUsers">
<input #firstName (keyup)="filterUsers(firstName.value)">
</div>
`
})
export class UserSearchComponent {
users: Observable<User[]>;
constructor(public userService: UserService) {
this.users = userService.getUsers();
}
filterUsers(search) {
this.filteredUsers = this.userService.users.filter(user =>
user.firstName.includes(search));
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `
<div *ngFor="let user of filteredUsers">
<input #firstName (keyup)="filterUsers(firstName.value)">
</div>
`
})
export class UserSearchComponent {
users: Observable<User[]>;
constructor(public userService: UserService) {
this.users = userService.getUsers();
}
filterUsers(search) {
this.filteredUsers = this.userService.users.filter(user =>
user.firstName.includes(search));
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `
<div *ngFor="let user of users | async">
<input #firstName (keyup)="filterUsers(firstName.value)">
</div>
`
})
export class UserSearchComponent {
users: Observable<User[]>;
constructor(public userService: UserService) {
this.users = userService.getUsers();
}
filterUsers(search) {
this.filteredUsers = this.userService.users.filter(user =>
user.firstName.includes(search));
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `
<div *ngFor="let user of users | async">
<input #firstName (keyup)="filterUsers(firstName.value)">
</div>
`
})
export class UserSearchComponent {
users: Observable<User[]>;
constructor(public userService: UserService) {
this.users = userService.getUsers();
}
filterUsers(search) {
this.filteredUsers = this.userService.users.filter(user =>
user.firstName.includes(search));
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `
<div *ngFor="let user of users | async">
<input #firstName (keyup)="firstNameSearch.next(firstName.value)">
</div>
`
})
export class UserSearchComponent {
users: Observable<User[]>;
firstNameSearch = new BehaviorSubject('');
constructor(public userService: UserService) {
this.users = userService.getUsers();
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `
<div *ngFor="let user of users | async">
<input #firstName (keyup)="firstNameSearch.next(firstName.value)">
</div>
`
})
export class UserSearchComponent {
users: Observable<User[]>;
firstNameSearch = new BehaviorSubject('');
constructor(public userService: UserService) {
this.users = userService.getUsers();
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `
<div *ngFor="let user of users | async">
<input #firstName (keyup)="firstNameSearch.next(firstName.value)">
</div>
`
})
export class UserSearchComponent {
users: Observable<User[]>;
firstNameSearch = new BehaviorSubject('');
constructor(public userService: UserService) {
this.users = Observable.combineLatest(
userService.getUsers(),
this.firstNameSearch,
(users, search) => {
return users.filter(user => user.firstName.includes(search));
}
);
}
http://rxmarbles.com/#combineLatest
userSearch.component.ts
@Component({
selector: 'user-search',
template: `<div *ngFor="let user of users | async"> ... </div>`
})
export class UserSearchComponent {
users: Observable<User[]>;
firstNameSearch = new BehaviorSubject('');
constructor(public userService: UserService) {
this.users = Observable.combineLatest(
userService.getUsers(),
this.firstNameSearch,
(users, search) => { ... }
);
}
removeUser(user: User) {
this.userService.users = this.userService.users.filter(u => u !== user);
this.filterUsers(this.firstName.nativeElement.value);
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `<div *ngFor="let user of users | async"> ... </div>`
})
export class UserSearchComponent {
users: Observable<User[]>;
firstNameSearch = new BehaviorSubject('');
constructor(public userService: UserService) {
this.users = Observable.combineLatest(
userService.getUsers(),
this.firstNameSearch,
(users, search) => { ... }
);
}
removeUser(user: User) {
this.userService.removeUser(user);
}
}
List Search
User Service
users$ = BehaviorSubject([
'User1',
'User2',
'User3'
])
List Search
User Service
users$ = BehaviorSubject([
'User1',
'User2',
'User3'
])
[
'User1',
'User2',
'User3'
]
List Search
User1 ✖
User2 ✖
User3 ✖
User Service
users$ = BehaviorSubject([
'User1',
'User2',
'User3'
])
[
'User1',
'User2',
'User3'
]
User1
User2
User3
List Search
User1 ✖
User2 ✖
User3 ✖
User1
User2
User3
User Service
users$ = BehaviorSubject([
'User1',
'User2',
'User3'
])
removeUser('User2')
List Search
User1 ✖
User2 ✖
User3 ✖
User1
User2
User3
User Service
users$ = BehaviorSubject([
'User1',
'User3'
])
removeUser('User2')
List Search
User1 ✖
User2 ✖
User3 ✖
User1
User2
User3
User Service
users$ = BehaviorSubject([
'User1',
'User3'
])
[
'User1',
'User3'
]
removeUser('User2')
List Search
User1 ✖
User3 ✖
User1
User3
User Service
users$ = BehaviorSubject([
'User1',
'User3'
])
[
'User1',
'User3'
]
removeUser('User2')
Angular 2 Component Communication - Talk by Rob McDiarmid
user.service.ts
export class UserService {
private users$ = new BehaviorSubject([]);
addUser(user) {
let users = [user, ...this.users$.getValue()];
this.users$.next(users);
}
removeUser(user) {
let users = this.users$.getValue().filter(u => u !== user);
this.users$.next(users);
}
getUsers() {
return this.users$.asObservable();
}
};
user.service.ts
export const userReducer = (users = [], action) => {
/*
addUser(user) {
let users = [user, ...this.users$.getValue()];
this.users$.next(users);
}
removeUser(user) {
let users = this.users$.getValue().filter(u => u !== user);
this.users$.next(users);
}
getUsers() {
return this.users$.asObservable();
}
*/
};
user.service.ts
export const userReducer = (users = [], action) => {
switch (action.type) {
/*
addUser(user) {
let users = [user, ...this.users$.getValue()];
this.users$.next(users);
}
removeUser(user) {
let users = this.users$.getValue().filter(u => u !== user);
this.users$.next(users);
}
getUsers() {
return this.users$.asObservable();
}
*/
}
};
user.service.ts
export const userReducer = (users = [], action) => {
switch (action.type) {
case 'CREATE_USER':
/*
let users = [user, ...this.users$.getValue()];
this.users$.next(users);
*/
case 'DELETE_USER':
/*
let users = this.users$.getValue().filter(u => u !== user);
this.users$.next(users);
*/
default:
/*
return this.users$.asObservable();
*/
}
};
user.service.ts
export const userReducer = (users = [], action) => {
switch (action.type) {
case 'CREATE_USER':
return [...users, User.fromMockData()];
case 'DELETE_USER':
/*
let users = this.users$.getValue().filter(u => u !== user);
this.users$.next(users);
*/
default:
/*
return this.users$.asObservable();
*/
}
};
user.service.ts
export const userReducer = (users = [], action) => {
switch (action.type) {
case 'CREATE_USER':
return [...users, User.fromMockData()];
case 'DELETE_USER':
return users.filter(user => user.id !== action.payload.id);
default:
/*
return this.users$.asObservable();
*/
}
};
user.service.ts
export const userReducer = (users = [], action) => {
switch (action.type) {
case 'CREATE_USER':
return [...users, User.fromMockData()];
case 'DELETE_USER':
return users.filter(user => user.id !== action.payload.id);
default:
return users;
}
};
app.module.ts
import {userReducer} from "./reducers/userReducer";
@NgModule({
imports: [StoreModule.provideStore({ users: userReducer })
],
declarations: [/*...*/],
providers: [/*...*/],
bootstrap: [/*...*/]
})
class AppModule { }
userSearch.component.ts
@Component({
selector: 'user-search',
template: `<div *ngFor="let user of users | async"> ... </div>`
})
export class UserSearchComponent {
users: Observable<User[]>;
firstNameSearch = new BehaviorSubject('');
constructor(public userService: UserService) {
this.users = Observable.combineLatest(
userService.getUsers(),
this.firstNameSearch,
(users, search) => { ... }
);
}
removeUser(user: User) {
this.userService.removeUser(user);
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `<div *ngFor="let user of users | async"> ... </div>`
})
export class UserSearchComponent {
users: Observable<User[]>;
firstNameSearch = new BehaviorSubject('');
constructor(public userService: UserService) {
this.users = Observable.combineLatest(
userService.getUsers(),
this.firstNameSearch,
(users, search) => { ... }
);
}
removeUser(user: User) {
this.userService.removeUser(user);
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `<div *ngFor="let user of users | async"> ... </div>`
})
export class UserSearchComponent {
users: Observable<User[]>;
firstNameSearch = new BehaviorSubject('');
constructor(public userService: UserService) {
this.users = Observable.combineLatest(
userService.getUsers(),
this.firstNameSearch,
(users, search) => { ... }
);
}
removeUser(user: User) {
this.userService.removeUser(user);
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `<div *ngFor="let user of users | async"> ... </div>`
})
export class UserSearchComponent {
users: Observable<User[]>;
firstNameSearch = new BehaviorSubject('');
constructor(public store: Store<AppState>) {
this.users = Observable.combineLatest(
userService.getUsers(),
this.firstNameSearch,
(users, search) => { ... }
);
}
removeUser(user: User) {
this.userService.removeUser(user);
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `<div *ngFor="let user of users | async"> ... </div>`
})
export class UserSearchComponent {
users: Observable<User[]>;
firstNameSearch = new BehaviorSubject('');
constructor(public store: Store<AppState>) {
this.users = Observable.combineLatest(
userService.getUsers(),
this.firstNameSearch,
(users, search) => { ... }
);
}
removeUser(user: User) {
this.userService.removeUser(user);
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `<div *ngFor="let user of users | async"> ... </div>`
})
export class UserSearchComponent {
users: Observable<User[]>;
firstNameSearch = new BehaviorSubject('');
constructor(public store: Store<AppState>) {
this.users = Observable.combineLatest(
store.select(s => s.users),
this.firstNameSearch,
(users, search) => { ... }
);
}
removeUser(user: User) {
this.userService.removeUser(user);
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `<div *ngFor="let user of users | async"> ... </div>`
})
export class UserSearchComponent {
users: Observable<User[]>;
firstNameSearch = new BehaviorSubject('');
constructor(public store: Store<AppState>) {
this.users = Observable.combineLatest(
store.select(s => s.users),
this.firstNameSearch,
(users, search) => { ... }
);
}
removeUser(user: User) {
this.userService.removeUser(user);
}
}
userSearch.component.ts
@Component({
selector: 'user-search',
template: `<div *ngFor="let user of users | async"> ... </div>`
})
export class UserSearchComponent {
users: Observable<User[]>;
firstNameSearch = new BehaviorSubject('');
constructor(public store: Store<AppState>) {
this.users = Observable.combineLatest(
store.select(s => s.users),
this.firstNameSearch,
(users, search) => { ... }
);
}
removeUser(user: User) {
this.store.dispatch({type: 'DELETE_USER', payload: {id: user.id}});
}
}
Takeaways
- Everything is a component!!!
Takeaways - Parent → Child
- Use an @Input() binding on child
component
- Use es6 setters or ngOnChanges() to
handle changes
- When @Input() doesn’t work, inject
a @ViewChild()
Takeaways - Child → Parent
- Use an @Output() binding on child
component
- Pass events to parent through an
EventEmitter()
@Output() doThing = new EventEmitter();
doThing.emit('some event');
- In the parent, get the payload of
the event with $event
<child (doThing)="handelThing($event)"></child>
- If you can’t use an @Output()
binding you can inject the parent
component directly into the child
Takeaways - Sibling → Sibling
- Use a service to communicate between
siblings
- Try to avoid sharing mutable state
- Use observables to push events out
from a service to components
private state$ = new BehaviorSubject<>({});
doSomething(thing) {
this.state$.next(thing);
}
Takeaways - ngrx/store (Redux)
- ngrx/store library brings redux like
approach to Angular 2
- Centralized state
- One way data flow
Further Reading
Angular Cookbook
Component Interaction
rxjs/store
github.com/ngrx/store
egghead.io
Building Angular 2
Components
egghead.io
Step-by-Step Async
JavaScript with RxJS
Rob McDiarmid
Slides: tinyurl.com/ng2-components
@robianmcd

More Related Content

What's hot (20)

PDF
What's Coming in Spring 3.0
Matt Raible
 
PDF
Workshop 17: EmberJS parte II
Visual Engineering
 
PDF
Simplified Android Development with Simple-Stack
Gabor Varadi
 
PDF
Practical Protocol-Oriented-Programming
Natasha Murashev
 
PDF
Workshop 20: ReactJS Part II Flux Pattern & Redux
Visual Engineering
 
PDF
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
Fwdays
 
PDF
Building Web Interface On Rails
Wen-Tien Chang
 
PDF
Workshop 23: ReactJS, React & Redux testing
Visual Engineering
 
PDF
Workshop 25: React Native - Components
Visual Engineering
 
PPTX
ReactJs presentation
nishasowdri
 
PPTX
Developing New Widgets for your Views in Owl
Odoo
 
PPT
Jsp/Servlet
Sunil OS
 
PPTX
Architecting Single Activity Applications (With or Without Fragments)
Gabor Varadi
 
PPTX
Paging Like A Pro
Gabor Varadi
 
PDF
Rails Best Practices
Wen-Tien Chang
 
PDF
React Native: JS MVC Meetup #15
Rob Gietema
 
PDF
State management in android applications
Gabor Varadi
 
PDF
Redux vs Alt
Uldis Sturms
 
PDF
Workshop 13: AngularJS Parte II
Visual Engineering
 
PDF
Workshop 14: AngularJS Parte III
Visual Engineering
 
What's Coming in Spring 3.0
Matt Raible
 
Workshop 17: EmberJS parte II
Visual Engineering
 
Simplified Android Development with Simple-Stack
Gabor Varadi
 
Practical Protocol-Oriented-Programming
Natasha Murashev
 
Workshop 20: ReactJS Part II Flux Pattern & Redux
Visual Engineering
 
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
Fwdays
 
Building Web Interface On Rails
Wen-Tien Chang
 
Workshop 23: ReactJS, React & Redux testing
Visual Engineering
 
Workshop 25: React Native - Components
Visual Engineering
 
ReactJs presentation
nishasowdri
 
Developing New Widgets for your Views in Owl
Odoo
 
Jsp/Servlet
Sunil OS
 
Architecting Single Activity Applications (With or Without Fragments)
Gabor Varadi
 
Paging Like A Pro
Gabor Varadi
 
Rails Best Practices
Wen-Tien Chang
 
React Native: JS MVC Meetup #15
Rob Gietema
 
State management in android applications
Gabor Varadi
 
Redux vs Alt
Uldis Sturms
 
Workshop 13: AngularJS Parte II
Visual Engineering
 
Workshop 14: AngularJS Parte III
Visual Engineering
 

Viewers also liked (17)

PPTX
Social, Mobile & The Future of Retail
Amrita Chopra
 
PPT
'Did He Really Say That?" effective component communication
Gus Sabatino
 
PPT
7 Principles of Communications
dexpan
 
PPTX
Dryland Systems Gender Component Communication
CGIAR Research Program on Dryland Systems
 
PPTX
React. Flux. Redux. by Andrey Kolodnitskiy
Valeriia Maliarenko
 
PPTX
Into the Land of lambda, One Programmer's Journey Into Functional Programming
Mike Pence
 
PDF
Understanding Redux — Ilya Gelman
500Tech
 
PDF
Social, Mobile & The Future of Retail
Amrita Chopra
 
PPTX
Teaching Business Writing and Oral Communication
Bovee and Thill
 
PDF
Dumb and smart components + redux (1)
Brecht Billiet
 
PDF
Application architecture doesn't have to suck
jtregunna
 
PPTX
Event Sourcing your AngularJS applications
Maurice De Beijer [MVP]
 
PPTX
React. Flux. Redux
Andrey Kolodnitsky
 
PDF
Progressive Web Apps
Kevin Dantas
 
DOCX
Derechos del niño
Tony Hotter
 
PPTX
Comercio electronico
mariangelarod
 
PDF
Ritusmoi_Kaushik_Resume
Ritusmoi Kaushik
 
Social, Mobile & The Future of Retail
Amrita Chopra
 
'Did He Really Say That?" effective component communication
Gus Sabatino
 
7 Principles of Communications
dexpan
 
Dryland Systems Gender Component Communication
CGIAR Research Program on Dryland Systems
 
React. Flux. Redux. by Andrey Kolodnitskiy
Valeriia Maliarenko
 
Into the Land of lambda, One Programmer's Journey Into Functional Programming
Mike Pence
 
Understanding Redux — Ilya Gelman
500Tech
 
Social, Mobile & The Future of Retail
Amrita Chopra
 
Teaching Business Writing and Oral Communication
Bovee and Thill
 
Dumb and smart components + redux (1)
Brecht Billiet
 
Application architecture doesn't have to suck
jtregunna
 
Event Sourcing your AngularJS applications
Maurice De Beijer [MVP]
 
React. Flux. Redux
Andrey Kolodnitsky
 
Progressive Web Apps
Kevin Dantas
 
Derechos del niño
Tony Hotter
 
Comercio electronico
mariangelarod
 
Ritusmoi_Kaushik_Resume
Ritusmoi Kaushik
 
Ad

Similar to Angular 2 Component Communication - Talk by Rob McDiarmid (20)

PDF
How to Mess Up Your Angular UI Components
cagataycivici
 
PDF
angular fundamentals.pdf angular fundamentals.pdf
NuttavutThongjor1
 
PDF
What is your money doing?
Alfonso Fernández
 
PDF
angular fundamentals.pdf
NuttavutThongjor1
 
PDF
Commit University - Exploring Angular 2
Commit University
 
PDF
Angular for Java Enterprise Developers: Oracle Code One 2018
Loiane Groner
 
PDF
Build Your Own Angular Component Library
Carlo Bonamico
 
PDF
Carlo Bonamico, Sonia Pini - So you want to build your (Angular) Component Li...
Codemotion
 
PPTX
yrs of IT experience in enterprise programming
narasimhulum1623
 
PDF
Angular 2 - The Next Framework
Commit University
 
PDF
Angular 2 overview in 60 minutes
Loiane Groner
 
PDF
Capstone ms2
TanishGupta44
 
PDF
An introduction to Angular2
Apptension
 
PDF
科特林λ學
彥彬 洪
 
PPTX
Building maintainable web apps with Angular MS TechDays 2017
Erik van Appeldoorn
 
PDF
VMWorld 2017 Hackathon training: Getting Started with Clarity
Jeeyun Lim
 
PDF
Angular 2 Essential Training
Patrick Schroeder
 
PPTX
Building a TV show with Angular, Bootstrap, and Web Services
David Giard
 
PDF
Reactive programming with RxJava
Jobaer Chowdhury
 
KEY
Re-architecting the designer-developer workflow
Richard Lord
 
How to Mess Up Your Angular UI Components
cagataycivici
 
angular fundamentals.pdf angular fundamentals.pdf
NuttavutThongjor1
 
What is your money doing?
Alfonso Fernández
 
angular fundamentals.pdf
NuttavutThongjor1
 
Commit University - Exploring Angular 2
Commit University
 
Angular for Java Enterprise Developers: Oracle Code One 2018
Loiane Groner
 
Build Your Own Angular Component Library
Carlo Bonamico
 
Carlo Bonamico, Sonia Pini - So you want to build your (Angular) Component Li...
Codemotion
 
yrs of IT experience in enterprise programming
narasimhulum1623
 
Angular 2 - The Next Framework
Commit University
 
Angular 2 overview in 60 minutes
Loiane Groner
 
Capstone ms2
TanishGupta44
 
An introduction to Angular2
Apptension
 
科特林λ學
彥彬 洪
 
Building maintainable web apps with Angular MS TechDays 2017
Erik van Appeldoorn
 
VMWorld 2017 Hackathon training: Getting Started with Clarity
Jeeyun Lim
 
Angular 2 Essential Training
Patrick Schroeder
 
Building a TV show with Angular, Bootstrap, and Web Services
David Giard
 
Reactive programming with RxJava
Jobaer Chowdhury
 
Re-architecting the designer-developer workflow
Richard Lord
 
Ad

Recently uploaded (20)

PDF
Advancing WebDriver BiDi support in WebKit
Igalia
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
PPTX
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
PPTX
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
PDF
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
PDF
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PDF
Biography of Daniel Podor.pdf
Daniel Podor
 
PDF
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PDF
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
PPTX
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
PDF
Staying Human in a Machine- Accelerated World
Catalin Jora
 
PPTX
Designing Production-Ready AI Agents
Kunal Rai
 
PDF
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
PDF
IoT-Powered Industrial Transformation – Smart Manufacturing to Connected Heal...
Rejig Digital
 
PDF
July Patch Tuesday
Ivanti
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
DOCX
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
PDF
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
DOCX
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
Advancing WebDriver BiDi support in WebKit
Igalia
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
Biography of Daniel Podor.pdf
Daniel Podor
 
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
Staying Human in a Machine- Accelerated World
Catalin Jora
 
Designing Production-Ready AI Agents
Kunal Rai
 
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
IoT-Powered Industrial Transformation – Smart Manufacturing to Connected Heal...
Rejig Digital
 
July Patch Tuesday
Ivanti
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 

Angular 2 Component Communication - Talk by Rob McDiarmid

  • 2. What is a component
  • 3. @Component({ selector: 'myComp', template: ` <div> Content: {{myVar}} </div> ` }) class MyComponent { myVar: string; constructor() { this.myVar = 'hello'; } } Output Input <html> <myComp></myComp> </html> <html> <myComp> <div> Content: hello </div> </myComp> </html>
  • 5. @Component({ selector: 'parent', template: ` <div> Parent content <child [param]="myVar"></child> Parent content </div> ` }) class ParentComponent { myVar = 'hello'; } @Component({ selector: 'child', template: '<div>Child: {{param}}</div>' }) class ChildComponent { @Input() param: string; } <html> <parent> <div> Parent content <child> Child hello </child> Parent content </div> </parent> </html> Output Input <html> <parent></parent> </html> wizardComp
  • 8. @Component({ selector: 'parent', template: ` <div> <child (childEvent)="handelChildEvent($event)"></child> </div> ` }) class ParentComponent { handelChildEvent(message) { console.log(message); } } @Component({ selector: 'child', template: ` <button (click)="childEvent.emit('clicked')">Click me</button> ` }) class ChildComponent { @Output() childEvent = new EventEmitter(); }
  • 11. @Component({ selector: 'sibling2', template: ` <button (click)="myService.increment()"> Increment </button>` }) class Sibling2Component { constructor(public myService: MyService) { } } @Component({ selector: 'sibling1', template: `{{myService.counter}}` }) class Sibling1Component { constructor(public myService: MyService) { } } class MyService { counter: number = 0; increment() { this.counter++; } }
  • 13. user.service.ts export class UserService { users: User[] = []; }
  • 14. user.service.ts export class UserService { private users$ = new BehaviorSubject([]); }
  • 15. user.service.ts export class UserService { private users$ = new BehaviorSubject([]); addUser(user) { let users = [user, ...this.users$.getValue()]; this.users$.next(users); } }
  • 16. user.service.ts export class UserService { private users$ = new BehaviorSubject([]); addUser(user) { let users = [user, ...this.users$.getValue()]; this.users$.next(users); } removeUser(user) { let users = this.users$.getValue().filter(u => u !== user); this.users$.next(users); } }
  • 17. user.service.ts export class UserService { private users$ = new BehaviorSubject([]); addUser(user) { let users = [user, ...this.users$.getValue()]; this.users$.next(users); } removeUser(user) { let users = this.users$.getValue().filter(u => u !== user); this.users$.next(users); } getUsers() { return this.users$.asObservable(); } }
  • 18. userSearch.component.ts @Component({ selector: 'user-search', template: ` <div *ngFor="let user of filteredUsers"> <input #firstName (keyup)="filterUsers(firstName.value)"> </div> ` }) export class UserSearchComponent { filteredUsers: User[]; constructor(public userService: UserService) { } filterUsers(search) { this.filteredUsers = this.userService.users.filter(user => user.firstName.includes(search)); } }
  • 19. userSearch.component.ts @Component({ selector: 'user-search', template: ` <div *ngFor="let user of filteredUsers"> <input #firstName (keyup)="filterUsers(firstName.value)"> </div> ` }) export class UserSearchComponent { users: Observable<User[]>; constructor(public userService: UserService) { this.users = userService.getUsers(); } filterUsers(search) { this.filteredUsers = this.userService.users.filter(user => user.firstName.includes(search)); } }
  • 20. userSearch.component.ts @Component({ selector: 'user-search', template: ` <div *ngFor="let user of filteredUsers"> <input #firstName (keyup)="filterUsers(firstName.value)"> </div> ` }) export class UserSearchComponent { users: Observable<User[]>; constructor(public userService: UserService) { this.users = userService.getUsers(); } filterUsers(search) { this.filteredUsers = this.userService.users.filter(user => user.firstName.includes(search)); } }
  • 21. userSearch.component.ts @Component({ selector: 'user-search', template: ` <div *ngFor="let user of users | async"> <input #firstName (keyup)="filterUsers(firstName.value)"> </div> ` }) export class UserSearchComponent { users: Observable<User[]>; constructor(public userService: UserService) { this.users = userService.getUsers(); } filterUsers(search) { this.filteredUsers = this.userService.users.filter(user => user.firstName.includes(search)); } }
  • 22. userSearch.component.ts @Component({ selector: 'user-search', template: ` <div *ngFor="let user of users | async"> <input #firstName (keyup)="filterUsers(firstName.value)"> </div> ` }) export class UserSearchComponent { users: Observable<User[]>; constructor(public userService: UserService) { this.users = userService.getUsers(); } filterUsers(search) { this.filteredUsers = this.userService.users.filter(user => user.firstName.includes(search)); } }
  • 23. userSearch.component.ts @Component({ selector: 'user-search', template: ` <div *ngFor="let user of users | async"> <input #firstName (keyup)="firstNameSearch.next(firstName.value)"> </div> ` }) export class UserSearchComponent { users: Observable<User[]>; firstNameSearch = new BehaviorSubject(''); constructor(public userService: UserService) { this.users = userService.getUsers(); } }
  • 24. userSearch.component.ts @Component({ selector: 'user-search', template: ` <div *ngFor="let user of users | async"> <input #firstName (keyup)="firstNameSearch.next(firstName.value)"> </div> ` }) export class UserSearchComponent { users: Observable<User[]>; firstNameSearch = new BehaviorSubject(''); constructor(public userService: UserService) { this.users = userService.getUsers(); } }
  • 25. userSearch.component.ts @Component({ selector: 'user-search', template: ` <div *ngFor="let user of users | async"> <input #firstName (keyup)="firstNameSearch.next(firstName.value)"> </div> ` }) export class UserSearchComponent { users: Observable<User[]>; firstNameSearch = new BehaviorSubject(''); constructor(public userService: UserService) { this.users = Observable.combineLatest( userService.getUsers(), this.firstNameSearch, (users, search) => { return users.filter(user => user.firstName.includes(search)); } ); }
  • 27. userSearch.component.ts @Component({ selector: 'user-search', template: `<div *ngFor="let user of users | async"> ... </div>` }) export class UserSearchComponent { users: Observable<User[]>; firstNameSearch = new BehaviorSubject(''); constructor(public userService: UserService) { this.users = Observable.combineLatest( userService.getUsers(), this.firstNameSearch, (users, search) => { ... } ); } removeUser(user: User) { this.userService.users = this.userService.users.filter(u => u !== user); this.filterUsers(this.firstName.nativeElement.value); } }
  • 28. userSearch.component.ts @Component({ selector: 'user-search', template: `<div *ngFor="let user of users | async"> ... </div>` }) export class UserSearchComponent { users: Observable<User[]>; firstNameSearch = new BehaviorSubject(''); constructor(public userService: UserService) { this.users = Observable.combineLatest( userService.getUsers(), this.firstNameSearch, (users, search) => { ... } ); } removeUser(user: User) { this.userService.removeUser(user); } }
  • 29. List Search User Service users$ = BehaviorSubject([ 'User1', 'User2', 'User3' ])
  • 30. List Search User Service users$ = BehaviorSubject([ 'User1', 'User2', 'User3' ]) [ 'User1', 'User2', 'User3' ]
  • 31. List Search User1 ✖ User2 ✖ User3 ✖ User Service users$ = BehaviorSubject([ 'User1', 'User2', 'User3' ]) [ 'User1', 'User2', 'User3' ] User1 User2 User3
  • 32. List Search User1 ✖ User2 ✖ User3 ✖ User1 User2 User3 User Service users$ = BehaviorSubject([ 'User1', 'User2', 'User3' ]) removeUser('User2')
  • 33. List Search User1 ✖ User2 ✖ User3 ✖ User1 User2 User3 User Service users$ = BehaviorSubject([ 'User1', 'User3' ]) removeUser('User2')
  • 34. List Search User1 ✖ User2 ✖ User3 ✖ User1 User2 User3 User Service users$ = BehaviorSubject([ 'User1', 'User3' ]) [ 'User1', 'User3' ] removeUser('User2')
  • 35. List Search User1 ✖ User3 ✖ User1 User3 User Service users$ = BehaviorSubject([ 'User1', 'User3' ]) [ 'User1', 'User3' ] removeUser('User2')
  • 37. user.service.ts export class UserService { private users$ = new BehaviorSubject([]); addUser(user) { let users = [user, ...this.users$.getValue()]; this.users$.next(users); } removeUser(user) { let users = this.users$.getValue().filter(u => u !== user); this.users$.next(users); } getUsers() { return this.users$.asObservable(); } };
  • 38. user.service.ts export const userReducer = (users = [], action) => { /* addUser(user) { let users = [user, ...this.users$.getValue()]; this.users$.next(users); } removeUser(user) { let users = this.users$.getValue().filter(u => u !== user); this.users$.next(users); } getUsers() { return this.users$.asObservable(); } */ };
  • 39. user.service.ts export const userReducer = (users = [], action) => { switch (action.type) { /* addUser(user) { let users = [user, ...this.users$.getValue()]; this.users$.next(users); } removeUser(user) { let users = this.users$.getValue().filter(u => u !== user); this.users$.next(users); } getUsers() { return this.users$.asObservable(); } */ } };
  • 40. user.service.ts export const userReducer = (users = [], action) => { switch (action.type) { case 'CREATE_USER': /* let users = [user, ...this.users$.getValue()]; this.users$.next(users); */ case 'DELETE_USER': /* let users = this.users$.getValue().filter(u => u !== user); this.users$.next(users); */ default: /* return this.users$.asObservable(); */ } };
  • 41. user.service.ts export const userReducer = (users = [], action) => { switch (action.type) { case 'CREATE_USER': return [...users, User.fromMockData()]; case 'DELETE_USER': /* let users = this.users$.getValue().filter(u => u !== user); this.users$.next(users); */ default: /* return this.users$.asObservable(); */ } };
  • 42. user.service.ts export const userReducer = (users = [], action) => { switch (action.type) { case 'CREATE_USER': return [...users, User.fromMockData()]; case 'DELETE_USER': return users.filter(user => user.id !== action.payload.id); default: /* return this.users$.asObservable(); */ } };
  • 43. user.service.ts export const userReducer = (users = [], action) => { switch (action.type) { case 'CREATE_USER': return [...users, User.fromMockData()]; case 'DELETE_USER': return users.filter(user => user.id !== action.payload.id); default: return users; } };
  • 44. app.module.ts import {userReducer} from "./reducers/userReducer"; @NgModule({ imports: [StoreModule.provideStore({ users: userReducer }) ], declarations: [/*...*/], providers: [/*...*/], bootstrap: [/*...*/] }) class AppModule { }
  • 45. userSearch.component.ts @Component({ selector: 'user-search', template: `<div *ngFor="let user of users | async"> ... </div>` }) export class UserSearchComponent { users: Observable<User[]>; firstNameSearch = new BehaviorSubject(''); constructor(public userService: UserService) { this.users = Observable.combineLatest( userService.getUsers(), this.firstNameSearch, (users, search) => { ... } ); } removeUser(user: User) { this.userService.removeUser(user); } }
  • 46. userSearch.component.ts @Component({ selector: 'user-search', template: `<div *ngFor="let user of users | async"> ... </div>` }) export class UserSearchComponent { users: Observable<User[]>; firstNameSearch = new BehaviorSubject(''); constructor(public userService: UserService) { this.users = Observable.combineLatest( userService.getUsers(), this.firstNameSearch, (users, search) => { ... } ); } removeUser(user: User) { this.userService.removeUser(user); } }
  • 47. userSearch.component.ts @Component({ selector: 'user-search', template: `<div *ngFor="let user of users | async"> ... </div>` }) export class UserSearchComponent { users: Observable<User[]>; firstNameSearch = new BehaviorSubject(''); constructor(public userService: UserService) { this.users = Observable.combineLatest( userService.getUsers(), this.firstNameSearch, (users, search) => { ... } ); } removeUser(user: User) { this.userService.removeUser(user); } }
  • 48. userSearch.component.ts @Component({ selector: 'user-search', template: `<div *ngFor="let user of users | async"> ... </div>` }) export class UserSearchComponent { users: Observable<User[]>; firstNameSearch = new BehaviorSubject(''); constructor(public store: Store<AppState>) { this.users = Observable.combineLatest( userService.getUsers(), this.firstNameSearch, (users, search) => { ... } ); } removeUser(user: User) { this.userService.removeUser(user); } }
  • 49. userSearch.component.ts @Component({ selector: 'user-search', template: `<div *ngFor="let user of users | async"> ... </div>` }) export class UserSearchComponent { users: Observable<User[]>; firstNameSearch = new BehaviorSubject(''); constructor(public store: Store<AppState>) { this.users = Observable.combineLatest( userService.getUsers(), this.firstNameSearch, (users, search) => { ... } ); } removeUser(user: User) { this.userService.removeUser(user); } }
  • 50. userSearch.component.ts @Component({ selector: 'user-search', template: `<div *ngFor="let user of users | async"> ... </div>` }) export class UserSearchComponent { users: Observable<User[]>; firstNameSearch = new BehaviorSubject(''); constructor(public store: Store<AppState>) { this.users = Observable.combineLatest( store.select(s => s.users), this.firstNameSearch, (users, search) => { ... } ); } removeUser(user: User) { this.userService.removeUser(user); } }
  • 51. userSearch.component.ts @Component({ selector: 'user-search', template: `<div *ngFor="let user of users | async"> ... </div>` }) export class UserSearchComponent { users: Observable<User[]>; firstNameSearch = new BehaviorSubject(''); constructor(public store: Store<AppState>) { this.users = Observable.combineLatest( store.select(s => s.users), this.firstNameSearch, (users, search) => { ... } ); } removeUser(user: User) { this.userService.removeUser(user); } }
  • 52. userSearch.component.ts @Component({ selector: 'user-search', template: `<div *ngFor="let user of users | async"> ... </div>` }) export class UserSearchComponent { users: Observable<User[]>; firstNameSearch = new BehaviorSubject(''); constructor(public store: Store<AppState>) { this.users = Observable.combineLatest( store.select(s => s.users), this.firstNameSearch, (users, search) => { ... } ); } removeUser(user: User) { this.store.dispatch({type: 'DELETE_USER', payload: {id: user.id}}); } }
  • 53. Takeaways - Everything is a component!!!
  • 54. Takeaways - Parent → Child - Use an @Input() binding on child component - Use es6 setters or ngOnChanges() to handle changes - When @Input() doesn’t work, inject a @ViewChild()
  • 55. Takeaways - Child → Parent - Use an @Output() binding on child component - Pass events to parent through an EventEmitter() @Output() doThing = new EventEmitter(); doThing.emit('some event'); - In the parent, get the payload of the event with $event <child (doThing)="handelThing($event)"></child> - If you can’t use an @Output() binding you can inject the parent component directly into the child
  • 56. Takeaways - Sibling → Sibling - Use a service to communicate between siblings - Try to avoid sharing mutable state - Use observables to push events out from a service to components private state$ = new BehaviorSubject<>({}); doSomething(thing) { this.state$.next(thing); }
  • 57. Takeaways - ngrx/store (Redux) - ngrx/store library brings redux like approach to Angular 2 - Centralized state - One way data flow
  • 58. Further Reading Angular Cookbook Component Interaction rxjs/store github.com/ngrx/store egghead.io Building Angular 2 Components egghead.io Step-by-Step Async JavaScript with RxJS