1

I am creating a custom component which loads the innerHTML from a remote source. My question is how can i load the content when app loads. Right now, the content loads when the page shows and its a small delay until the text appears. Is there an event i can attach to that component to load the content when the app loads?

This is how my component looks like:

import {Component} from 'angular2/core'
import {DataProvider} from '../../providers/DataProvider'

@Component({

    'selector': 'ck-tos',
    templateUrl: 'build/directives/ckTos/ckTos.html',
    providers: [[Cashklick]],
})

export class ckTos {

    content: String = "";

    constructor(private DataProvider: DataProvider) {

        DataProvider.load('pages', 'terms').subscribe(
            data => {

                let response = data.json();
                if (response.content)
                    this.content = response.content;
                else if (response.error)
                    this.content = response.error;
                else
                    this.content = "Error: Unable to get any data ...";

            },
            err => {this.content = "Error: Unable to get any data ...";},
            () => console.log('DataProvider service for page terms completed')
        );
    }

}

When i open the app, i want this component to have content variable loaded and used without calling the remote service each time the component is rendered.

keepwalking
  • 2,644
  • 6
  • 28
  • 63

2 Answers2

1

You could implement the following mechanism into your service:

export class DataProvider {
  constructor(private http:Http) {
  }

  load() {
    if (this.data) {
      return Observable.of(this.data);
    } else {
      return this.http.get(...)
                 .map(...)
                 .do(data => {
                   this.data = data;
                 });
  }
}

You need to share your service for the whole application:

bootstrap(AppComponent, [ DataProvider ]);

Be careful not to specify DataProvider within the providers attribute of your components.

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • It needs to be implement at the component level, since the DataProvider is used in multiple locations and it loads different data, i don't want to cache that. – keepwalking Mar 14 '16 at 12:42
  • Okay! Make sense! Do you use routing for your components? – Thierry Templier Mar 14 '16 at 12:43
  • I am using ionic 2 and i am quite new on both, i don't see a bootstrap() declaration inside ionic 2 demo apps and documentation. You have any idea how can i make that service globally on Ionic 2? I am not using routing in ionic 2. – keepwalking Mar 14 '16 at 12:44
  • So use the `providers` attribute of your main component. Because of hierarchical injectors, it will be shared with other components... – Thierry Templier Mar 14 '16 at 12:46
  • You can do something because components will be instantiated each time you use them. The @Günter's solution allows you to keep the same instance but it only applies with routing... `@CanActivate` could also be what you're looking for but it's also in the context of routing. In your case, the only way is to mix my solution with what @Günter proposes in this question... (if you want this: " without calling the remote service each time the component is rendered") – Thierry Templier Mar 14 '16 at 12:54
  • Thanks, i've managed to cache the requests and using Observable.of i am able to serve the cached content to the components. Thanks a lot both of you. – keepwalking Mar 14 '16 at 19:30
1

You can either implement canReuse() https://angular.io/docs/ts/latest/api/router/CanReuse-interface.html so the component instance isn't recreated when navigating away from and back to the same component

or you you can move that code to a service (probably into DataProvider or another service that depends no DataProvider) and inject that service instead. The service instance will be kept alive by DI including the data.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Reuse sounds good, but how can i load it when the entire apps loads? Right now it loads when i navigate to the page where that component is present inside the html. – keepwalking Mar 14 '16 at 12:45
  • You keep it like it is. When you later navigate back to the component, everything should be as it was left (constructor not called again). – Günter Zöchbauer Mar 14 '16 at 12:46
  • In Ionic 2 do you have any idea what i need to import in order for CanReuse, OnReuse to work? Right now i am getting: Cannot find name 'OnReuse'. – keepwalking Mar 14 '16 at 12:54
  • I don't know Ionic. In TS it's `OnReuse` from `angular2/router`. If this isn't supported in Ionic, just adding a method `routerCanReuse(next: ComponentInstruction, prev: ComponentInstruction) { return true; }` to your component should do. (you also can remove the types from the parameters so you don't need to import them as well. See also this example https://github.com/angular/angular/blob/df6d2d1e23de0960c79f975cb18f9da6ef6761c3/modules/angular2/examples/router/ts/reuse/reuse_example.ts#L28 also the `routerOnReuse()` so you can do some additional initialization on reuse. – Günter Zöchbauer Mar 14 '16 at 12:59
  • I don't think this is working, i was able to implement them but they never fire. I guess this is since Ionic 2 is not using Routing, its using a navigation component to move to pages. – keepwalking Mar 14 '16 at 13:09
  • Oh, sorry for the noise :-/ Then it's probably best to wrap the data in a service. – Günter Zöchbauer Mar 14 '16 at 13:11