Angular 2
घटक बातचीत
खोज…
परिचय
विभिन्न निर्देशों और घटकों के बीच जानकारी साझा करें।
इनपुट बाइंडिंग के साथ माता-पिता से बच्चे का डेटा पास करें
HeroChildComponent में दो इनपुट गुण हैं, आमतौर पर @Input सजावट के साथ सजी है।
import { Component, Input } from '@angular/core';
import { Hero } from './hero';
@Component({
selector: 'hero-child',
template: `
<h3>{{hero.name}} says:</h3>
<p>I, {{hero.name}}, am at your service, {{masterName}}.</p>
`
})
export class HeroChildComponent {
@Input() hero: Hero;
@Input('master') masterName: string;
}
एक सेटर के साथ इंटरसेप्ट इनपुट प्रॉपर्टी बदलती है
माता-पिता से एक मूल्य पर अवरोधन और कार्य करने के लिए एक इनपुट संपत्ति सेटर का उपयोग करें।
बच्चे में नाम इनपुट संपत्ति का सेटर NameChildComponent एक नाम से व्हाट्सएप को ट्रिम करता है और डिफ़ॉल्ट पाठ के साथ एक खाली मान को बदलता है।
import { Component, Input } from '@angular/core';
@Component({
selector: 'name-child',
template: '<h3>"{{name}}"</h3>'
})
export class NameChildComponent {
private _name = '';
@Input()
set name(name: string) {
this._name = (name && name.trim()) || '<no name set>';
}
get name(): string { return this._name; }
}
यहाँ NameParentComponent सभी स्थानों के साथ एक नाम सहित नाम विविधता का प्रदर्शन कर रहा है:
import { Component } from '@angular/core';
@Component({
selector: 'name-parent',
template: `
<h2>Master controls {{names.length}} names</h2>
<name-child *ngFor="let name of names" [name]="name"></name-child>
`
})
export class NameParentComponent {
// Displays 'Mr. IQ', '<no name set>', 'Bombasto'
names = ['Mr. IQ', ' ', ' Bombasto '];
}
माता-पिता बच्चे की घटना सुनते हैं
चाइल्ड कंपोनेंट एक EventEmitter प्रॉपर्टी को उजागर करता है, जिसके साथ कुछ होने पर घटनाओं का उत्सर्जन करता है। अभिभावक उस इवेंट प्रॉपर्टी से जुड़ जाता है और उन ईवेंट्स पर प्रतिक्रिया देता है।
बच्चे की EventEmitter संपत्ति एक आउटपुट प्रॉपर्टी है, जो आमतौर पर @ VuterCompent में देखी गई @Output सजावट से सजी होती है:
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'my-voter',
template: `
<h4>{{name}}</h4>
<button (click)="vote(true)" [disabled]="voted">Agree</button>
<button (click)="vote(false)" [disabled]="voted">Disagree</button>
`
})
export class VoterComponent {
@Input() name: string;
@Output() onVoted = new EventEmitter<boolean>();
voted = false;
vote(agreed: boolean) {
this.onVoted.emit(agreed);
this.voted = true;
}
}
एक बटन पर क्लिक करने से एक सच्चे या गलत (बूलियन पेलोड) का उत्सर्जन होता है।
मूल VoteTakerComponent एक ईवेंट हैंडलर (onVoted) को बांधता है जो चाइल्ड ईवेंट पेलोड ($ इवेंट) पर प्रतिक्रिया करता है और एक काउंटर अपडेट करता है।
import { Component } from '@angular/core';
@Component({
selector: 'vote-taker',
template: `
<h2>Should mankind colonize the Universe?</h2>
<h3>Agree: {{agreed}}, Disagree: {{disagreed}}</h3>
<my-voter *ngFor="let voter of voters"
[name]="voter"
(onVoted)="onVoted($event)">
</my-voter>
`
})
export class VoteTakerComponent {
agreed = 0;
disagreed = 0;
voters = ['Mr. IQ', 'Ms. Universe', 'Bombasto'];
onVoted(agreed: boolean) {
agreed ? this.agreed++ : this.disagreed++;
}
}
अभिभावक स्थानीय चर के माध्यम से बच्चे के साथ बातचीत करते हैं
एक माता-पिता घटक बाल संपत्तियों को पढ़ने या बच्चे के तरीकों को लागू करने के लिए डेटा बाइंडिंग का उपयोग नहीं कर सकते हैं। हम दोनों बच्चे तत्व के लिए एक टेम्प्लेट रेफरेंस वेरिएबल बनाकर कर सकते हैं और फिर उस वेरिएबल को पेरेंट टेम्प्लेट के भीतर निम्न उदाहरण में देखा जा सकता है।
हमारे पास एक बच्चा काउंटडाउनटाइमरकंपोनेंट है जो बार-बार शून्य तक गिरता है और एक रॉकेट लॉन्च करता है। इसमें घड़ी को नियंत्रित करने वाले तरीके शुरू और बंद हो गए हैं और यह अपने स्वयं के टेम्प्लेट में एक उलटी गिनती स्थिति संदेश प्रदर्शित करता है।
import { Component, OnDestroy, OnInit } from '@angular/core';
@Component({
selector: 'countdown-timer',
template: '<p>{{message}}</p>'
})
export class CountdownTimerComponent implements OnInit, OnDestroy {
intervalId = 0;
message = '';
seconds = 11;
clearTimer() { clearInterval(this.intervalId); }
ngOnInit() { this.start(); }
ngOnDestroy() { this.clearTimer(); }
start() { this.countDown(); }
stop() {
this.clearTimer();
this.message = `Holding at T-${this.seconds} seconds`;
}
private countDown() {
this.clearTimer();
this.intervalId = window.setInterval(() => {
this.seconds -= 1;
if (this.seconds === 0) {
this.message = 'Blast off!';
} else {
if (this.seconds < 0) { this.seconds = 10; } // reset
this.message = `T-${this.seconds} seconds and counting`;
}
}, 1000);
}
}
आइए देखते हैं CountdownLocalVarParentComponent जो टाइमर घटक को होस्ट करता है।
import { Component } from '@angular/core';
import { CountdownTimerComponent } from './countdown-timer.component';
@Component({
selector: 'countdown-parent-lv',
template: `
<h3>Countdown to Liftoff (via local variable)</h3>
<button (click)="timer.start()">Start</button>
<button (click)="timer.stop()">Stop</button>
<div class="seconds">{{timer.seconds}}</div>
<countdown-timer #timer></countdown-timer>
`,
styleUrls: ['demo.css']
})
export class CountdownLocalVarParentComponent { }
माता-पिता घटक बच्चे की शुरुआत और रुकने के तरीकों और न ही इसकी सेकंड प्रॉपर्टी के लिए डेटा बाइंड नहीं कर सकते।
हम बच्चे के घटक का प्रतिनिधित्व करने वाले टैग () पर एक स्थानीय चर (#timer) रख सकते हैं। यह हमें स्वयं बाल घटक और उसके किसी भी गुण या तरीके को अभिभावक टेम्पलेट के भीतर से एक्सेस करने की क्षमता का संदर्भ देता है।
इस उदाहरण में, हम माता-पिता के बटन को बच्चे की शुरुआत में रोकते हैं और बच्चे की सेकंड की संपत्ति को प्रदर्शित करने के लिए प्रक्षेप का उपयोग करते हैं।
यहां हम माता-पिता और बच्चे को एक साथ काम करते हुए देखते हैं।
अभिभावक ViewChild कहते हैं
स्थानीय चर दृष्टिकोण सरल और आसान है। लेकिन यह सीमित है क्योंकि पैरेंट-चाइल्ड वायरिंग पूरी तरह से पेरेंट टेम्पलेट के भीतर ही होनी चाहिए। मूल घटक के पास बच्चे तक कोई पहुंच नहीं है।
अगर हम पैरेंट कंपोनेंट क्लास के एक उदाहरण को पढ़ने या लिखने के लिए चाइल्ड कंपोनेंट वैल्यूज़ पढ़ते हैं या चाइल्ड कंपोनेंट मेथड को कॉल करते हैं तो हम लोकल वैरिएबल तकनीक का इस्तेमाल नहीं कर सकते।
जब पैरेंट कंपोनेंट क्लास को उस तरह की पहुंच की आवश्यकता होती है, तो हम चाइल्ड कंपोनेंट को व्यूचाइल्ड के रूप में पेरेंट में इंजेक्ट करते हैं।
हम एक ही उलटी गिनती टाइमर उदाहरण के साथ इस तकनीक का वर्णन करेंगे। हम इसका स्वरूप या व्यवहार नहीं बदलेंगे। चाइल्ड काउंटडाउनटाइमरकंपोनेंट भी ऐसा ही है।
हम केवल प्रदर्शन के उद्देश्य के लिए स्थानीय चर से ViewChild तकनीक पर स्विच कर रहे हैं। यहाँ जनक है, काउंटडाउन व्यू चिल्डपैरेंटकम्पोनेंट:
import { AfterViewInit, ViewChild } from '@angular/core';
import { Component } from '@angular/core';
import { CountdownTimerComponent } from './countdown-timer.component';
@Component({
selector: 'countdown-parent-vc',
template: `
<h3>Countdown to Liftoff (via ViewChild)</h3>
<button (click)="start()">Start</button>
<button (click)="stop()">Stop</button>
<div class="seconds">{{ seconds() }}</div>
<countdown-timer></countdown-timer>
`,
styleUrls: ['demo.css']
})
export class CountdownViewChildParentComponent implements AfterViewInit {
@ViewChild(CountdownTimerComponent)
private timerComponent: CountdownTimerComponent;
seconds() { return 0; }
ngAfterViewInit() {
// Redefine `seconds()` to get from the `CountdownTimerComponent.seconds` ...
// but wait a tick first to avoid one-time devMode
// unidirectional-data-flow-violation error
setTimeout(() => this.seconds = () => this.timerComponent.seconds, 0);
}
start() { this.timerComponent.start(); }
stop() { this.timerComponent.stop(); }
}
बच्चे को माता-पिता के घटक वर्ग में देखने के लिए थोड़ा और काम करना पड़ता है।
हम ViewChild डेकोरेटर और AfterViewInit जीवनचक्र हुक के संदर्भ आयात करते हैं।
हम बच्चे को उलटी गिनती गिनते हैं। निजी घड़ी में निजी टाइमरकंपनी की संपत्ति को देखें।
#Timer स्थानीय चर घटक मेटाडेटा से चला गया है। इसके बजाय हम बटन को मूल घटक के प्रारंभ और स्टॉप विधियों से बांधते हैं और टिक घटक को मूल घटक के सेकंड विधि के आसपास एक प्रक्षेप में प्रस्तुत करते हैं।
ये तरीके सीधे इंजेक्ट किए गए टाइमर घटक को एक्सेस करते हैं।
NgAfterViewInit जीवनचक्र हुक एक महत्वपूर्ण शिकन है। टाइमर घटक तब तक उपलब्ध नहीं है जब तक कि कोणीय मूल दृश्य प्रदर्शित नहीं करता है। इसलिए हम शुरुआत में 0 सेकंड प्रदर्शित करते हैं।
तब कोणीय ने ngAfterViewInit जीवनचक्र हुक को कॉल किया, जिस समय पर उलटी गिनती सेकंड के मूल दृश्य को अपडेट करने के लिए बहुत देर हो चुकी है। कोणीय के यूनिडायरेक्शनल डेटा फ्लो नियम हमें एक ही चक्र में माता-पिता के दृश्य को अपडेट करने से रोकता है। सेकंड प्रदर्शित करने से पहले हमें एक मोड़ पर रुकना होगा।
हम एक टिक को प्रतीक्षा करने के लिए सेटटाइमआउट का उपयोग करते हैं और फिर सेकंड विधि को संशोधित करते हैं ताकि यह टाइमर घटक से भविष्य के मान ले।
माता-पिता और बच्चे एक सेवा के माध्यम से संवाद करते हैं
एक मूल घटक और उसके बच्चे एक सेवा साझा करते हैं जिसका इंटरफ़ेस परिवार के भीतर द्वि-दिशात्मक संचार को सक्षम करता है।
सेवा उदाहरण का दायरा मूल घटक और उसके बच्चे हैं। इस घटक सबट्री के बाहर घटकों की सेवा या उनके संचार तक कोई पहुंच नहीं है।
यह MissionService, MissionControlComponent को कई AstronautComponent बच्चों से जोड़ता है।
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class MissionService {
// Observable string sources
private missionAnnouncedSource = new Subject<string>();
private missionConfirmedSource = new Subject<string>();
// Observable string streams
missionAnnounced$ = this.missionAnnouncedSource.asObservable();
missionConfirmed$ = this.missionConfirmedSource.asObservable();
// Service message commands
announceMission(mission: string) {
this.missionAnnouncedSource.next(mission);
}
confirmMission(astronaut: string) {
this.missionConfirmedSource.next(astronaut);
}
}
MissionControlComponent दोनों उस सेवा का उदाहरण प्रदान करता है जिसे वह अपने बच्चों के साथ साझा करता है (प्रदाताओं मेटाडेटा सरणी के माध्यम से) और उस उदाहरण को अपने निर्माता के माध्यम से स्वयं में इंजेक्ट करता है:
import { Component } from '@angular/core';
import { MissionService } from './mission.service';
@Component({
selector: 'mission-control',
template: `
<h2>Mission Control</h2>
<button (click)="announce()">Announce mission</button>
<my-astronaut *ngFor="let astronaut of astronauts"
[astronaut]="astronaut">
</my-astronaut>
<h3>History</h3>
<ul>
<li *ngFor="let event of history">{{event}}</li>
</ul>
`,
providers: [MissionService]
})
export class MissionControlComponent {
astronauts = ['Lovell', 'Swigert', 'Haise'];
history: string[] = [];
missions = ['Fly to the moon!',
'Fly to mars!',
'Fly to Vegas!'];
nextMission = 0;
constructor(private missionService: MissionService) {
missionService.missionConfirmed$.subscribe(
astronaut => {
this.history.push(`${astronaut} confirmed the mission`);
});
}
announce() {
let mission = this.missions[this.nextMission++];
this.missionService.announceMission(mission);
this.history.push(`Mission "${mission}" announced`);
if (this.nextMission >= this.missions.length) { this.nextMission = 0; }
}
}
एस्ट्रोनॉटकम्पोनेंट भी अपने कंस्ट्रक्टर में सेवा को इंजेक्ट करता है। प्रत्येक एस्ट्रोनॉटकम्पोनेंट, मिशनकंट्रोलकम्पोनेंट का एक बच्चा है और इसलिए वह अपने माता-पिता की सेवा प्राप्त करता है:
import { Component, Input, OnDestroy } from '@angular/core';
import { MissionService } from './mission.service';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector: 'my-astronaut',
template: `
<p>
{{astronaut}}: <strong>{{mission}}</strong>
<button
(click)="confirm()"
[disabled]="!announced || confirmed">
Confirm
</button>
</p>
`
})
export class AstronautComponent implements OnDestroy {
@Input() astronaut: string;
mission = '<no mission announced>';
confirmed = false;
announced = false;
subscription: Subscription;
constructor(private missionService: MissionService) {
this.subscription = missionService.missionAnnounced$.subscribe(
mission => {
this.mission = mission;
this.announced = true;
this.confirmed = false;
});
}
confirm() {
this.confirmed = true;
this.missionService.confirmMission(this.astronaut);
}
ngOnDestroy() {
// prevent memory leak when component destroyed
this.subscription.unsubscribe();
}
}
ध्यान दें कि हम सदस्यता पर कब्जा कर लेते हैं और जब एस्ट्रोनॉटकंपोनेंट नष्ट हो जाता है तो सदस्यता समाप्त कर देते हैं। यह एक मेमोरी-लीक गार्ड कदम है। इस ऐप में कोई वास्तविक जोखिम नहीं है क्योंकि एक एस्ट्रोनॉटकंपोनेंट का जीवनकाल ऐप के जीवनकाल के समान ही है। यह हमेशा एक अधिक जटिल अनुप्रयोग में सच नहीं होगा।
हम इस गार्ड को MissionControlComponent में नहीं जोड़ते हैं, क्योंकि अभिभावक के रूप में, यह मिशन सेवा के जीवनकाल को नियंत्रित करता है। द हिस्ट्री लॉग दर्शाता है कि संदेश माता-पिता मिशनकंट्रोलकम्पोनेंट और एस्ट्रोनॉटकंपोनेंट बच्चों के बीच यात्रा करते हैं, जो सेवा द्वारा सुविधा प्रदान करते हैं: