דלג לתוכן הראשי

Share data between components

אם אנחנו רוצים לשתף מידע בין קומפוננטות שונות, אנחנו יכולים להשתמש בפונקציות של ה-service.

בתצוגה יש לנו מונה פשוט עם כפתורי +-.

counter.component.html
<div>
<button (click)="plus()">+</button>{{ counterValue }}<button (click)="minus()">-</button>
</div>

ב-class אנחנו יוצרים מונה עם ערך ראשוני של 0 וקוראים לפונקציות של פלוס ומינוס. הפונקציות האלה קוראות לפונקציות המתאימות ב-service.

counter.component.ts
constructor(private countService: CountService) {}
counterValue = 0;


ngOnInit(): void {
this.counterValue = this.countService.counterValue;
}

plus() {
this.countService.plus();
}

minus() {
this.countService.minus();
}

הפונקציות של ה-service משנות את הערך של המונה הגלובלי.

counter.service.ts
counterValue = 0;

plus(){
this.counterValue++;
}

minus(){
this.counterValue--;
}

שימוש ב-Subject

בעיה אם יהיו לנו כמה מופעים של הערך מקומפוננטות שונות, שינוי של הערך בקומפוננטה אחת לא יעדכן את הערך באחרות.

פתרון שימוש במשתנה subject במקום במשתנה רגיל.

counter.service.ts
counterSubject = new Subject<number>();

plus() {
this.counterValue++;
this.counterSubject.next(this.counterValue);
}

minus() {
this.counterValue--;
this.counterSubject.next(this.counterValue);
}

כדי לקלוט את השינויים מהקומפוננטות, אנחנו צריכים לרשום אותם להאזין לשינויים.

counter.component.ts
constructor(private countService: CountService) {}
counterValue = 0;

ngOnInit(): void {
this.countService.counterSubject.subscribe(newCounterValue =>
this.counterValue = newCounterValue);
}

plus() {
this.countService.plus();
}

minus() {
this.countService.minus();
}

בעיה counterSubject מוגדר ה-public וכל פונקציה יכולה לגשת ולשנות אותו.

פתרון הגדרת counterSubject כ-private ויצירת פונציית גישה לערך שלו.

counter.service.ts
private counterSubject = new Subject<number>();

get counter$(){
return this.counterSubject.asObservable();
}

plus() {
this.counterValue++;
this.counterSubject.next(this.counterValue);
}

minus() {
this.counterValue--;
this.counterSubject.next(this.counterValue);
}

כשאנחנו מגדירים משתנה asObservable אפשר רק לצפות בערך שלו אבל לא לשנות אותו.

counter.component.ts
ngOnInit(): void {
this.countService.counter$.subscribe(newCounterValue =>
this.counterValue = newCounterValue);
}

Late Joiners

בעיה אם נוסיף קומפוננטה חדשה לדף, היא לא תקבל מראש את הערך שכבר יש בתוך המשתנה של ה-service, Late Joiners.

למשל, אם יש לי אוטנטיקציה של משתמש, הקומפוננטה החדשה לא תדע על זה ולא תוכל להעריך האם המשתמש רשום או לא ולבצע על פי זה פעולות.

פתרון אנחנו רוצים לתת את הערך הנוכחי גם למי שהצטרף מאוחר ולכן נשתמש ב-BehaviorSubject. הוא עושה בדיוק מה ש-subject עושה + נותן מידע ל-subscriber חדשים על הערך שיש בו.

counter.service.ts
private counterSubject = new BehaviorSubject<number>(0);

plus() {
const lastValue = this.counterSubject.value;
this.counterSubject.next(lastValue + 1);
}

קריאה ל-service מתוך service

אנחנו יכולים לקרוא ל-service אחד מתוך service אחר.

אם רוצים לקרוא ל-serviceB מתוך serviceA:

  1. מוסיפים את ה-service שרוצים, במקרה הזה B, לתוך ה-constructor של serviceA.
  2. ל-serviceA צריך להיות Injectable decorator.
  3. מוסיפים את serviceB ל-providers של app.module או של הקומפוננטה שבה משתמשים ב-serviceA.