I have issue where I want to receive data into my property ponent 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 ponent 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 ponent.
I have issue where I want to receive data into my property ponent 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 ponent 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 ponent.
2 Answers
Reset to default 7You can create a subscription in your service that notifies if event list changed
eventChanged = new Subject<Event[]>();
in your ponent, 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 ponent 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 ponents, 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 ponent EventViewer, gets the list, as well as subscribes for any changes
event-viewer.ponent.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.ponent.html',
styleUrls: ['./event-viewer.ponent.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.ponent.html
<ul>
<li *ngFor="let event of events">{{event}}</li>
</ul>
Lastly we want an event editor ponent
event-editor.ponent.ts
import { Component, OnInit } from '@angular/core';
import {EventService} from '../event.service';
@Component({
selector: 'app-event-edit',
templateUrl: './event-edit.ponent.html',
styleUrls: ['./event-edit.ponent.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.ponent.ts
<button (click)="addEvent()">Add event {{eventNumber}}</button>
In the module of choice we'll obviously have to declare these ponents, enlist the provider
app.module.ts
@NgModule({
declarations: [
EventViewerComponent,
EventEditComponent
],
imports: [
CommonModule
],
providers: [EventService]
})
So then in then we render both ponents
app.ponent.ts
<app-event-viewer></app-event-viewer>
<app-event-edit></app-event-edit>
Now every time we click on button in one ponent, the other ponent gets the updated list
For example:
export class YourService {
private refreshSource: Subject<boolean> = new Subject();
public refreshStream: Observable<boolean> = this.refreshSource.asObservable();
endpoint_url = "https://<your_backend>/api/";
constructor(private client: HttpClient) {}
// get collection
cget(queryParams: any): Promise<Obj[]> {
return this.client.get<Obj[]>(this.endpoint_url + 'objs').toPromise();
}
// create one object
post(obj: Obj): Promise<Obj> {
const res = this.client.post(
this.endpoint_url + 'objs',
JSON.stringify(obj),
this.requestParams);
return res.toPromise().then((response) => {
obj.id = response['id'];
this.refreshSource.next(true);
return obj as Obj;
});
}
export class YourComponent implements OnDestroy {
subscriptions: Subscription[] = [];
success:boolean;
failure:boolean;
loading:boolean;
constructor(private ys: YourService) {
this.subscriptions.push( this.ys.refreshStrem.subscribe(() => this.load()) );
}
async load() {
this.yourObjs = await this.ys.cget();
}
async submit() {
this.loading = true;
try {
const response = this.ys.post(this.obj)
this.success = true;
} catch (error) {
console.log('error', error);
this.failure = true;
} finally {
this.loading = false;
}
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => subscription.unsubscribe());
}