How to user services with angular2

I am finding it difficult to use services in my code. Main question is:

  • shall i subscribe to subscription in my service and get the data from that subscription. Later on get the data through one of the methods of Service?

What is the best way to use services. Please provide your suggestions.

I agree it would be useful to have more documentation on this. In the socially tutorial services aren’t used, so it would be nice to have a version of the tutorial that does use services or at least a link to the code from socially using services…

I think i’ve got this working now. This is my code as it stands, although i’d like someone to confirm whether or not this is the correct/best method:

Component 1 (uses an array of documents):

import { Component } from '@angular/core';
import { MeteorComponent } from 'angular2-meteor';
import { Job } from "../../../../both/models/job.model";
import { JobService } from './job.service';
import template from './jobs.component.html';

@Component({
  selector: 'jobs',
  providers: [ JobService ],
  template
})

export class JobsComponent extends MeteorComponent {
  constructor (private _jobService: JobService) {
    super();
  }

  getJobs() {
    return this._jobService.getJobs();
  }
}

These are used in the template like so:

<div *ngFor="let job of getJobs() | async">
</div>

Component 2 (finds one document from these jobs):

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/map';
import { MeteorObservable } from 'meteor-rxjs';

import { Job } from "../../../../both/models/job.model";

import { JobService } from './job.service';

import template from './job.component.html';

@Component({
  selector: 'job',
  providers: [JobService],
  template
})

export class JobComponent {
  paramsSub: Subscription;

  jobSub: Subscription;
  jobId: string;
  job: Job;

  constructor( private route: ActivatedRoute,
               private _jobService: JobService ) {}

  ngOnInit() {
    this.paramsSub = this.route.params
      .map(params => params['jobId'])
      .subscribe(jobId => {
        if (this.jobSub) {
          this.jobSub.unsubscribe();
        }

        this.jobSub = MeteorObservable.subscribe('jobs', this.jobId).zone().subscribe(() => {
          this.job = this._jobService.getJobById(jobId);
        });
      });
  }

  ngOnDestroy() {
    this.paramsSub.unsubscribe();
    this.jobSub.unsubscribe();
  }
}

And the service to go with both of these:

import { Injectable } from '@angular/core';
import { Observable } from "rxjs";

import { MeteorObservable } from 'meteor-rxjs';

import { Job } from "../../../../both/models/job.model";
import { Jobs } from "../../../../both/collections/jobs.collection";

@Injectable()
export class JobService {
  private jobs : Observable<Job[]>;
  private job : Observable<Job>;

  constructor() {
    this.jobs = Jobs.find({});
    MeteorObservable.subscribe("jobs").subscribe();
  }

  public getJobs() : Observable<Job[]> {
    return this.jobs;
  }

  public getJobById(jobId) : Observable<Job> {
    return Jobs.findOne({"_id":jobId});
  }
}

I am getting the following warnings though so if someone could help me debug these I would really appreciate it:

Type 'Job' is not assignable to type 'Observable<Job>'.
  Property '_isScalar' is missing in type 'Job'.
Type 'Observable<Job>' is not assignable to type 'Job'.
Property 'name' is missing in type 'Observable<Job>'.
1 Like

I have a similar need, where I need to create an Authentication service which covers login, logout, signup, recover password etc. I followed the socially app and I am trying to place the different functions in a service.

  1. where to put the services code, with the component or separate out in server to be secured…

Not sure if this is relevant for you anymore - and also I’m by no means an expert so I might be completly wrong here - but by saying

public getJobById(jobId) : Observable<Job> {
     return Jobs.findOne({"_id":jobId});
}

you define the return value for this method to be an Observable of a job-object. I’m pretty sure this part

return Jobs.findOne({"_id":jobId});

doesn’t return an Observable though. Maybe your IDE or the documentation can give you a hint here.

Try

public getJobById(jobId) : Job {
     return Jobs.findOne({"_id":jobId});
}

and let me know if it helped.

Again, I’m no expert when it comes to Meteor or Angular whatsoever, but I think I had an similar issue not too long ago and that was the reason.