1

I have a behaviour in Angular 2 project that i don't know how to solve. I'm using webpack with Angular 2 2.3 (if this helps).

I have a complex project with structure like this:

- index.ts
- app.module.ts
- app.component.ts
- app.routes.ts
- services
     - login.service.ts
- +innerapp
     - inner.routes.ts
     - inner.module.ts
     - inner.component.ts
     - inner.component.html
     - services
         -inner.service.ts
     - insideinner
         - insideinner.component.ts
         - insideinner.component.html
         - header
             - header.component.ts
             - header.component.html
         - form
             - form.component.ts
             - form.component.html

When you execute shows login and then route to +innerapp. Inner.component.ts loads inner.services.ts and do a http call for data. A lot of data is moved from server and a let of BehaivorSubjects are initialized inside inner.service.ts.

All works fine, but in a moment user clicks button and loads form.component.ts with a big form. User fills form and click submit, in this moment inner.service is called to add data form. My surprise is inner.service haven't data, it's just initialised.

Code below.

//inner.routes.ts
export const routes = [
  { path: '', children: [
  { path: '', component: InnerComponent },
  { path: 'form', component: FormComponent },
  ]},
];

inner.module.ts

import { routes } from './inner.routes';
import { InnerComponent } from './inner.component';
import { FormComponent } from './insideinner/form/form.component';

// Services
import { InnerService } from './service/inner.service';

@NgModule({
  declarations: [
    // Components / Directives/ Pipes
    InnerComponent,
    FormComponent
  ],
  imports: [
    RouterModule.forChild(routes),
  ],
  providers: [
    InnerService
  ]
})
export class InnerModule {
  public static routes = routes;
}

inner.component.ts:

@Component({
  selector: 'inner',
  templateUrl: './inner.component.html'
})
export class InnerComponent implements OnInit {

  constructor ( private innerService: innerService ) {

    this.innerService.fetchData()
      .subscribe(
        (response) => {
          this.innerService.addData(response.json());
        },
    (error) => {
      alert(error);
    }
  );

}

services/inner.services.ts

import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs';
import { Headers, RequestOptions, Http, Response } from '@angular/http';

@Injectable()
export class InnerService {

  // Observable string streams
  public readonly data: Observable<string>;

  // Observable string sources
  private _data: BehaviorSubject<string> = new BehaviorSubject(null);

  // private properties
  private options: RequestOptions;

  constructor( public http: Http ) {
    this.data = this._user.asObservable();

    // http standard values
    let token = localStorage.getItem('token');
    let cabs = new Headers({ Authorization: 'Bearer ' + token });
    this.options = new RequestOptions({ headers: cabs });
  }

  // Service message commands
  public addData (t: string) {
    this._data.next(t);
  }

  public saveData(t: string) {

    return this.http.post(blabla,
      {
        data: t
      },
      this.options
    ).map((res: Response) => {
      this.addData(t);
      return true;
    }).catch(this.handleError);

  }

  private handleError (error: any) {
    //code
  }

  public fetchData(): Observable<any> {
    return this.http.get(blabla, this.options)
      .map((res) => { return res.body })
      .catch(this.handleError);
  }
}

insideinner/form/form.component.ts

import { Component, OnInit, ViewEncapsulation } from '@angular/core';

// services & others
import { InnerService } from '../../services/inner.service';

@Component({
  selector: 'add-members',
  templateUrl: './form.component.html',
  encapsulation: ViewEncapsulation.None
})
export class FormComponent implements OnInit  {

  constructor(
    private fb: FormBuilder,
    private innerService: InnerService
  ) {}

  public ngOnInit() {
    this.showForm = false;
  }

  public onSubmit(value: string) {

    this.innerService.saveData(value); //Fail here, inner service are without data 
  }

  public showAdd() {
    this.showForm = true;
  }
}

I read a lot of docs and read here similar problems, but solutions aren't working for me.

EDIT 2017-05-31 I think that is dupe question. I see that problem is related with lazyload in routes. I try this solution: Angular 2 lazy loaded module - service not singleton

and this solution: Angular 2 How to make singleton service available to lazy loaded modules

But no one work for me. I want to say that this project is in garbage and I began again with Angular 1.6 but I'm really interested in solve this problem to make future projects.

Mork
  • 365
  • 5
  • 18
  • according to your setup, it should work properly. Anything that you missed to mention? – micronyks Apr 24 '17 at 16:38
  • 1
    Have you defined innerService in root/app module too? – micronyks Apr 24 '17 at 16:39
  • I tried it and then removed. I've added now but not work. InnerService is a new instance when I access to form. – Mork Apr 24 '17 at 16:43
  • Everything seems okay to me. My concerned is with appmodule only. But that is but different story altogether. just make sure you are not using `providers:[innerService]` statement anywhere else except module level. Here it seems that it creates different instances of the service. Its hard to guess with this setup of your project. – micronyks Apr 24 '17 at 16:47
  • I am experiencing something very similar I think. Haven't found a solution yet either. How do I best link my example, so maybe both examples together lead to more understanding? Should I open a separate question and link it? Should I post an answer although it's really a question? A comment is too small to describe. – Worp Apr 25 '17 at 18:16

0 Answers0