2

I am using angular2-webpack-starter, As Route is not that standard yet in the "2.0.0-rc.1", they are using @angular/route-depricated for routing purposes. Now

This is my Service

@Injectable()
export class JSTreeService {

  constructor(private http: Http) {

  }
  // Uses http.get() to load a single JSON file
  getData(): Observable<IDataItem[]> {
    return this.http.get('url')
      .map((res: Response) => res.json());

  }


}

This is my Main Component where I subscribed the service and passed it to another service to pass it to other components

@Component({
  selector: 'app',
  pipes: [],
  providers: [JSTreeService, HTTP_PROVIDERS, SharedData],
  directives: [],
  encapsulation: ViewEncapsulation.None,

  template: `
    <header>
      <md-toolbar color="primary">
        <span>{{ name }}</span>
        <nav>
          <ul>
            <li router-active>
              <a [routerLink]=" ['Index'] ">Index</a>
            </li>
            |
            <li router-active>
              <a [routerLink]=" ['Home'] ">Home</a>
            </li>
            |
            <li router-active>
              <a [routerLink]=" ['About'] ">About</a>
            </li>
            |
            <li router-active>
              <a [routerLink]=" ['Items'] ">Items</a>
            </li>
          </ul>
        </nav>
      </md-toolbar>
    </header>
    <md-progress-bar mode="indeterminate" color="primary" *ngIf="loading"></md-progress-bar>

    <main>
      <router-outlet></router-outlet>
    </main>


})
@RouteConfig([
  { path: '/', name: 'Index', component: Home, useAsDefault: true },
  { path: '/home', name: 'Home', component: Home },


  { path: '/item', name: 'Items', component: ItemComponent },
  // Async load a component using Webpack's require with es6-promise-loader and webpack `require`
  { path: '/about', name: 'About', loader: () => require('es6-promise!./about')('About') }
])
export class App {

  dataItem: IDataItem[];

  // @Input() flag
  constructor(
    public appState: AppState,
    private _itemData: JSTreeService,
    private _sharedData: SharedData) {

  }
  getData() {
    this._itemData.getData()
      .subscribe(
      // the first argument is a function which runs on success
      (data: IDataItem[]) => {
        this.dataItem = data;
      },
      // the second argument is a function which runs on error
      err => console.error(err),
      // the third argument is a function which runs on completion
      () => (this._sharedData.dataItem = this.dataItem)

      );

    this.flag = 1;
  }

  ngOnInit() {
    console.log('Initial App State', this.appState.state);
    console.log('hello `Item` component');
    this.getData();
  }

}

This is my route component

@Component({
  selector: 'Item',
  template: require('./item.html'),
  providers: [
  ]
})
export class ItemComponent  {
  dataItem: IDataItem[];
  flag: number;

  constructor(private _sharedData: SharedData) {

  }

  ngOnInit() {
    // console.log(this.dataItem);
    this.dataItem = this._sharedData.dataItem;

  }

  ngOnDestroy() {
    // this.dataItem = this._sharedData.dataItem;
  }
}

This is the SharedService

@Injectable()
export class SharedData {
  constructor() {

  }
  dataItem:IDataItem[];


}

Here is my item.template

<div class="">
  <label *ngFor="let item of dataItem"> <input type="checkbox" name="checkbox" value="value"> {{item.text}} <br></label>
</div>

I can successfully pass the data from appcomponent to 'ItemComponent'. So whenever I load my app it subscribes the http call and pass the data to SharedService. And when I Click Item it routes to ItemComponent, it shows the data. Now my problem is Every time I route to Item, every time it recreates the ItemComponent so my data goes away. And I dont want it. I want to store the state of that component. And is this a good way to pass data between components. I am a novice in Angular2 , any kind of help will be appreciated :) My Updated ItemComponent :

@Component({
  selector: 'Item',
  template: require('./item.html'),
  providers: [
    // JSTreeService,

  ]
})
export class ItemComponent implements CanReuse, OnReuse {
  dataItem: IDataItem[];
  flag: number;

  constructor(private _sharedData: SharedData) {
    // this.dataItem = params.get('dataitems');


  }

  ngOnInit() {
    // console.log(this.dataItem);
    this.dataItem = this._sharedData.dataItem;

  }
  routerCanReuse(next: ComponentInstruction, prev: ComponentInstruction) {


    return true;
  }
  routerOnReuse(next: ComponentInstruction, prev: ComponentInstruction) {
    //  this.name = next.params['name'];
    this.dataItem = this._sharedData.dataItem;
    console.log(this.dataItem);
  }
  ngOnDestroy() {
    // this.dataItem = this._sharedData.dataItem;
  }
}

And yes I am using @angular/router-depricated from webpackstarter kit

pd farhad
  • 6,352
  • 2
  • 28
  • 47

1 Answers1

1

Keep the data in a service and fetch it from there when the component is recreated (when you route back to the route with this component)

For cases where navigation only changes parameter values, you can implement @CanReuse() and return true, so the router doesn't dispose and recreated the component in this situation.

routerCanReuse(nextInstruction: ComponentInstruction, prevInstruction: ComponentInstruction) : boolean |
<boolean> {
  return true; 
}

This is not yet implemented in the new RC.1 router.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • I edited my question's description at the very beginning and also updated my ItemComponent class down below , Can you please check my again and enlighten my faults , Thanks anyway :) – pd farhad May 12 '16 at 09:01
  • One problem I see is that you don't wait for `http.get()` to succeed before you copy from (`this.dataItem = this._sharedData.dataItem;`). This should already cause problems when the application or component is loaded the first time, not only when you route back a 2nd time. Copying data around is dangerous if you want it to be synchronized. http://stackoverflow.com/questions/36271899/what-is-the-correct-way-to-share-the-result-of-an-angular-2-http-network-call-in shows ways where each component interested in data fetches it from an observable itself – Günter Zöchbauer May 12 '16 at 09:17
  • Your code in the questino contains to much code that is not relevant to the problem which makes it cumbersome to read. – Günter Zöchbauer May 12 '16 at 09:17
  • I edited my question again and tried to delete all the irrelevant code , thank you :) – pd farhad May 12 '16 at 09:33
  • I would inject `JsTreeService` into `SharedData` and make `SharedData` to get the data itself instead using the `AppComponent` to copy from `JsTreeService` to `SharedData`. `SharedData` should use an `Observable` (`BehaviorSubject` for example) and interested component should subscribe to this observable to get notified about updates. This way it is ensured that components get updates when data arrives or changes. – Günter Zöchbauer May 12 '16 at 10:22