How to return data from Meteor.call on angular service


#1

I am trying to return data from server using meteor methods from inside a angular2 service
my question is how to return the data to my component if the call happen async? It was easy when the calls was inside my component, but moving it to a service made me get stuck.

@Injectable()
export class PartiesService extends MeteorComponent {
 
    list() {
        return this.call("parties.list",(err,data)=>{
            console.log(data)
            return data;
        });
    }

    add(item) {
        this.call("parties.insert", item, (err,data)=>{
        });
    }

    delete(item){
        this.call("parties.delete", item, (err,data)=>{
        });
    }
}

#2

Hi @adrianolsk You can use RxJS 5.

Basically, you create an Observable, and then subscribe it in the component.

Check this 🏄 Subscribe data in Service using RxJS 5


#3

I made it work, but I’am not sure if it is the best way.

My service

import {MeteorComponent} from "angular2-meteor/build/index";
import {Observable} from "rxjs/Rx";
import {Injectable} from "@angular/core";

@Injectable()
export class PartiesService extends MeteorComponent {

    getAll():Observable<Array<Object>> {      

        return Observable.create(observer => {

            this.call("parties.list", (err, data)=> {
                if (err) {                   
                    observer.error(err);
                } else {
                    observer.next(data);
                    observer.complete();
                }
            });

            return () => {              
                console.log("unsubscribed")
            };
        });
    }  

    add(item) {
        this.call("parties.insert", item, (err, data)=> {
        });
    }

    delete(item) {
        this.call("parties.delete", item, (err, data)=> {
        });
    }
}

My Component

import {Component, NgZone} from '@angular/core';
import {PartiesService} from "../../services/PartiesService";

@Component({
    templateUrl: '/imports/components/parties/parties.component.html',
    selector: "parties"
})
export class PartiesComponent {

    parties:Array<Object>;

    constructor(private partiesService:PartiesService, private ngZone: NgZone) {
        this.parties = [];
        this.getParties();
    }

    delete(item) {
        this.partiesService.delete(item._id);
        this.getParties();
    }

    getParties(){
        this.partiesService.getAll().subscribe(parties => {

            this.ngZone.run(() => {
                this.parties = parties;
            });

        }, err =>{
            console.error(err);
        });
    }
}

What do you think @Hongbo_Miao?


#4

You can div ngFor=“let listitem of myservice.list”

Why not declare a Mongo.Cursor in your service, fill it with a query and use it directly?

I’m finding that the least code in the component, the better. Handle events, instantiate, but have the template use the service data directly.

In the template myobservable$ | async subscribes to the observable.

I’m still working this out, but a template that talks to a service can talk to a different service with the same API interface, allowing reuse. My app will have lots of similar tree type views with similar actions, so even a different component service combination with the same outward facing interfaces can save me lots of development time.


#5

I am not using a Mongo.Cursor because I change the data before return, so it’s different from the collection and I may also get data from others sources, not just mongo.


#6

Hi, @adrianolsk
I believe there is always better way. That is my feeling when I am using Angular 2 and Meteor.
I am also trying to explore all potential of Angular 2 and Meteor. : )

If I found any really good way, I will share it here.

There are so much potential for Angular 2 and Meteor, just keep learning!


#7

@Hongbo_Miao
Have you found a better solution for this problem? If so, please do post it here.
Thanks!


#8

The RxJS 5 is a good way. That is one of best thing in Angular 2. We should take advantage of it.

The new Observable based Meteor API will help us do this easily. Check: