最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to subscribe object from service in Angular 25? - Stack Overflow

programmeradmin1浏览0评论

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.

Share Improve this question edited Dec 30, 2017 at 12:15 Adriano asked Dec 29, 2017 at 18:40 AdrianoAdriano 9242 gold badges14 silver badges41 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

You 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());

}
发布评论

评论列表(0)

  1. 暂无评论