How to subscribe object from service in Angular 2/5?
You can create a subscription in your service that notifies if event list changed
eventChanged = new Subject<Event[]>();
in your component, you'll want to subscribe to the eventChanged, in case event list has changed
this.subscription = this.eventService.eventChanged
.subscribe(
(event: Event[]) => {
this.events = events;
}
);
Then add a next
in your service to notify of event changed every time any component updates it, and make it resend the list of events, or whatever you want
addEvent(event: Event) {
this.events.push(event);
this.eventChanged.next(this.events.slice());
}
Update: With example
In case we have event viewer, event editor components, and event service
Setup event service to have a subject (event changed), accessor (get events) adder (update events)
import { Injectable } from '@angular/core';
import {Subject} from 'rxjs/Subject';
@Injectable()
export class EventService {
eventChanged = new Subject<string[]>();
events: string[] = [
'Pizza Party',
'Hackacthon',
'Movie Night'
]
constructor() { }
addEvent(event: string) {
this.events.push(event);
this.eventChanged.next(this.events.slice());
}
getEvents() {
return this.events.slice();
}
}
Then component EventViewer, gets the list, as well as subscribes for any changes
event-viewer.component.ts
import { Component, OnInit } from '@angular/core';
import {EventService} from '../event.service';
import {Subscription} from 'rxjs/Subscription';
@Component({
selector: 'app-event-viewer',
templateUrl: './event-viewer.component.html',
styleUrls: ['./event-viewer.component.css']
})
export class EventViewerComponent implements OnInit {
subscription: Subscription;
events: string[] = this.eventService.getEvents();
constructor(private eventService: EventService) { }
ngOnInit() {
this.subscription = this.eventService.eventChanged
.subscribe(
(events: string[]) => {
this.events = events;
}
)
}
}
So then we render it out
event-viewer.component.html
<ul>
<li *ngFor="let event of events">{{event}}</li>
</ul>
Lastly we want an event editor component
event-editor.component.ts
import { Component, OnInit } from '@angular/core';
import {EventService} from '../event.service';
@Component({
selector: 'app-event-edit',
templateUrl: './event-edit.component.html',
styleUrls: ['./event-edit.component.css']
})
export class EventEditComponent implements OnInit {
eventNumber: number = 1;
constructor(private eventService: EventService) { }
ngOnInit() {
}
addEvent()
{
this.eventService.addEvent(this.eventNumber.toString())
this.eventNumber++;
}
}
and render a button for the user to control
event-editor.component.ts
<button (click)="addEvent()">Add event {{eventNumber}}</button>
In the module of choice we'll obviously have to declare these components, enlist the provider
app.module.ts
@NgModule({
declarations: [
EventViewerComponent,
EventEditComponent
],
imports: [
CommonModule
],
providers: [EventService]
})
So then in then we render both components
app.component.ts
<app-event-viewer></app-event-viewer>
<app-event-edit></app-event-edit>
Now every time we click on button in one component, the other component gets the updated list
Related videos on Youtube
Adriano
Updated on June 04, 2022Comments
-
Adriano almost 2 years
I have issue where I want to receive data into my property component after they came from the server.
I made something like this in Service:
private events: Event[] = []; eventChanged = new Subject<any>(); // Edit: added an observable constructor(private http: HttpClient) { this.http.get<Event[]>(this.baseUrl) .subscribe(events => this.events = events); this.eventChanged.next(this.events.slice()); //Edit: added an information to subscribers that events list changed } getEvents(): Observable<Event[]> { return this.eventChanged.asObservable(); } // Edit: now I use this method to enables subscribers to observable /* I don't use that method after Edit showAllEvents(): Event[] { return [...this.events]; } */
And then I use method
showAllEvents()
into mine component like this:private events: Event[] = []; private calendarEvents: CalendarEvent[] = []; subscription: Subscription; // Edit: Added a Subscription getInterestedEvents() { // this.events = this.el.showAllEvents(); <-- I changed it into observable this.subscription = this.el.getEvents() .subscribe( (events) => { this.events = events; }); this.events.forEach(eachEvent => { let calendarEvent: CalendarEvent = { start: subDays(startOfDay(new Date()), 1), end: addDays(new Date(), 1), title: eachEvent.name, color: colors.red } this.calendarEvents.push(calendarEvent); }) }
I don't know how to make
this.events
to wait for data from service. Any ideas? On every page it looks different and now I feel like a fool.Edit
I made a subscribe and observable but still
this.el.getEvents().subscribe...
dosen't return any data in my component. -
Adriano over 6 yearsUnfortunately it doesn't work, I add
this.eventChanged.next(this.events.slice());
in mine Service constructor and I also test methodaddEvent()
andthis.eventService.eventChanged.subscribe(..
didn't notice any changes. It was not called again. -
Iancovici over 6 years@Adriano, created a complete example
-
Adriano over 6 years@lancovici That subscribing don't works when I get data from server. Only thanks to this :
events: string[] = this.eventService.getEvents();
it displays data after page reload. -
Iancovici over 6 years@Adriano check your rxjs in package.json, and let me know what version it is. Also do you see any errors when inspecting page?
-
Adriano over 6 years@lancovici it's "rxjs": "^5.5.2", No I didn't notice any errors. I make subscibing works but only after I add a next 'Event'
-
Iancovici over 6 years@Adriano, Not sure how you are setup right now, maybe put it in stackblitz.com. in this example I'm showing you how to get the list on initialization from a service, then whenever someone update the list, the service updates list, then calls next on subject, and inputs the list. The component that needs to listen, will have to get the list inside its subscription callback.
-
Adriano over 6 yearsLet us continue this discussion in chat.