Wednesday, July 20, 2016

Angular2 Shared Services

I've been working with Angular2 for a few weeks now and I like it quite a bit, but sharing data between components was a bit of a pain until I figured out what was going on. At first I had a service (let's call it DataService) that I was trying to use to share data between multiple components (cleverly called Component1 and Component2).

Here is my service:


import { Injectable, Component, OnInit, Input } from '@angular/core';
import { Http, Response, Headers, HTTP_PROVIDERS } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/toPromise';
import { DataObject } from '../base/data';

@Injectable()
export class DataService implements OnInit {
    public data: DataObject = new DataObject;

    constructor(public _http: Http) {
    };

    ngOnInit() {

    }

    getData() {
        var aPromise = this._http.get('/api/data')
            .map((response: Response) => response.json())
            .toPromise()
            .catch(err => console.log(err));

        aPromise.then(dataFromServer => this.data = dataFromServer);
    };
}

And here is my first non-working component:

import { Component, OnInit } from '@angular/core';
import { Http, Headers, HTTP_PROVIDERS } from '@angular/http';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/filter';
import {CORE_DIRECTIVES, FORM_DIRECTIVES, NgClass, NgIf} from '@angular/common';
import { DataService } from '../services/data.service';
import { ProcessFormComponent } from './process-form.component';

@Component({
    selector: 'processes',
    templateUrl: 'partials/app.component.html',
    styleUrls: ['styles/app.component.css'],
    directives: [
        ProcessFormComponent
    ],
    providers: [
        HTTP_PROVIDERS,
DataService
    ]
})

export class Component1 implements OnInit {
    title = 'Data Engine Configurator Extrordinaire';

    constructor(
        private DataService: DataService,
        public toastr: ToastsManager
    ) { }

    ngOnInit() {
        this.DataService.getData();
    }

    onSelectProcess(process: Process){
        this.DataService.selectedProcess = process;
    }

    createProcess() {
        this.DataService.selectedProcess = new Process;
    }
}

And here is my second non-working component:

import { Component, OnInit } from '@angular/core';
import { Http, Headers, HTTP_PROVIDERS } from '@angular/http';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/filter';
import {CORE_DIRECTIVES, FORM_DIRECTIVES, NgClass, NgIf} from '@angular/common';
import { DataService } from '../services/data.service';
import { SubProcessFormComponent } from './process-form.component';

@Component({
    selector: 'subprocesses',
    templateUrl: 'partials/sub.component.html',
    styleUrls: ['styles/app.component.css'],
    directives: [
        SubProcessFormComponent
    ],
    providers: [
        HTTP_PROVIDERS,
DataService
    ]
})

export class Component2 implements OnInit {
    title = 'Data Engine Configurator Extrordinaire';

    constructor(
        private DataService: DataService,
        public toastr: ToastsManager
    ) { }

    ngOnInit() {
        this.DataService.getData();
    }

    onSelectProcess(process: Process){
        this.DataService.selectedProcess = process;
    }

    createProcess() {
        this.DataService.selectedProcess = new Process;
    }
}

And main.ts:

/////<reference path="../../node_modules/@angular/platform-browser/src/browser.d.ts"/>
///<reference path="C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.8\lib.es6.d.ts" />
import { bootstrap } from '@angular/platform-browser-dynamic';
import {Component} from "@angular/core";
import {Http, HTTP_PROVIDERS, Response} from "@angular/http";
import 'rxjs/add/operator/map';
import { AppComponent } from '../components/app.component';
import { disableDeprecatedForms, provideForms } from '@angular/forms';

bootstrap(AppComponent, [
    disableDeprecatedForms(),
    provideForms(),
    HTTP_PROVIDERS
])

    .catch((err: any) => console.error(err));


No matter what I did, all of the data in the service was blanked out or undefined in each component whenever I called it. Then, thanks to the efforts of a few other bloggers and some blood, sweat and tears, I figured out how to actually share the service. You need to add the provider for the service in main and DO NOT add it in the components.

My new working main (changes in bold):

/////<reference path="../../node_modules/@angular/platform-browser/src/browser.d.ts"/>
///<reference path="C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.8\lib.es6.d.ts" />
import { bootstrap } from '@angular/platform-browser-dynamic';
import {Component} from "@angular/core";
import {Http, HTTP_PROVIDERS, Response} from "@angular/http";
import 'rxjs/add/operator/map';
import { AppComponent } from '../components/app.component';
import { disableDeprecatedForms, provideForms } from '@angular/forms';
import { DataService } from '../services/Data.service';

bootstrap(AppComponent, [
    disableDeprecatedForms(),
    provideForms(),
    HTTP_PROVIDERS,
    DataService
])
    .catch((err: any) => console.error(err));

My new working component1

import { Component, OnInit } from '@angular/core';
import { Http, Headers, HTTP_PROVIDERS } from '@angular/http';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/filter';
import {CORE_DIRECTIVES, FORM_DIRECTIVES, NgClass, NgIf} from '@angular/common';
import { DataService } from '../services/data.service';
import { ProcessFormComponent } from './process-form.component';

@Component({
    selector: 'processes',
    templateUrl: 'partials/app.component.html',
    styleUrls: ['styles/app.component.css'],
    directives: [
        ProcessFormComponent
    ],
    providers: [
        HTTP_PROVIDERS
    ]
})

export class Component1 implements OnInit {
    title = 'Data Engine Configurator Extrordinaire';

    constructor(
        private DataService: DataService,
        public toastr: ToastsManager
    ) { }

    ngOnInit() {
        this.DataService.getData();
    }

    onSelectProcess(process: Process){
        this.DataService.selectedProcess = process;
    }

    createProcess() {
        this.DataService.selectedProcess = new Process;
    }
}

And here is my second working component:

import { Component, OnInit } from '@angular/core';
import { Http, Headers, HTTP_PROVIDERS } from '@angular/http';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/filter';
import {CORE_DIRECTIVES, FORM_DIRECTIVES, NgClass, NgIf} from '@angular/common';
import { DataService } from '../services/data.service';
import { SubProcessFormComponent } from './process-form.component';

@Component({
    selector: 'subprocesses',
    templateUrl: 'partials/sub.component.html',
    styleUrls: ['styles/app.component.css'],
    directives: [
        SubProcessFormComponent
    ],
    providers: [
        HTTP_PROVIDERS,
    ]
})

export class Component2 implements OnInit {
    title = 'Data Engine Configurator Extrordinaire';

    constructor(
        private DataService: DataService,
        public toastr: ToastsManager
    ) { }

    ngOnInit() {
        this.DataService.getData();
    }

    onSelectProcess(process: Process){
        this.DataService.selectedProcess = process;
    }

    createProcess() {
        this.DataService.selectedProcess = new Process;
    }
}

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.