[SOLVED] Observable ? ngOnInit?

Edit : I solved it too by adding :
this.currentCategories = [];
in constructor. But I have questions :

Can you give me please an advice about :

  • when to use ngOnInit instead of constructor? I know that ngOnInit is called after the constructor and called after the first ngOnChanges(). Should i use constructor to only setup Dependency Injection ? and ngOnInit for all other stuff? like init list…
  • when to use observable?

Question before edit
Hello everyone .

I have a litle mistake : I have a category list that it can be updated by a personn in a back office.
I want to add search in this list later (so i think about my implementation)

I get data for the list by an API Rest Service.

This is my code :

@Component({
  selector: 'page-cards-category',
  templateUrl: 'cards-category.html'
 })
export class CardsCategoryPage  {

  currentCategories : Category[];
  url  = 'my_default_url';

  constructor(public navCtrl: NavController, public categories : Categories, public navParams: NavParams ) {


      if (navParams.get("category"))
         this.url =  navParams.get("category");
      this.categories.query(this.url).subscribe(data => {
             
                this.currentCategories = data.subCategories || data.elements;
               
            },
            err => {
                console.log(err);
            });
    }

   ionViewDidLoad() {
      console.log('ionViewDidLoad CardsCategoryPage');
    }


   getRows()
   {

      let tripleCol = [];
      let currentCategoriesLength = this.currentCategories.length;

      for (let i = 0; i < currentCategoriesLength; i += 3) {
         let trio = [];
         trio.push(this.currentCategories[i]);
         if (i + 1 < currentCategoriesLength) {
             trio.push(this.currentCategories[i + 1]);
         }
        if (i + 2 < currentCategoriesLength) {
            trio.push(this.currentCategories[i + 2]);
        }
        tripleCol.push(trio);
     }
     return tripleCol;
  }
}

and html :

<ion-grid>
     <ion-row *ngFor="let row of getRows() ">
          <ion-col *ngFor="let cat of row">
               {{cat.name}}
          </ion-col>
     </ion-row>
</ion-grid>

When I use this, I got Runtime error : this.currentCategories is undefined. (It seems to be like that currentCategories object is not completely initialized

If I add a test in getRows() like

  getRows()
  {
       if (this.currentCategories)
       {
           ....
       }
    
  }

It works.

So, I think there is a better approach for this : use Observable? or NgOnInit ?
If you have an advice it will be great :slight_smile:
Thanks a lot

Use a constructor to define variables with default values, like this.myObservable = new Observable<boolean>();. Use ionViewWillEnter() to define what the Observable actually does, so to speak. Unsubscribe from the Observable in ionViewWillLeave() or similar.

I use ngOnInit() in components and services where you don’t enter or leave. I am not sure there is much performance difference in Ionic between putting things there, or putting them in the constructor. It’s more a way for me to make a conceptual difference in my code between initialization and computation.

The basic reason for doing this is that Ionic builds factories for pages on startup, so the more computation you put in your constructors, the longer it will take to start your app. So you want to push that work to just before it is needed, i.e., just before you enter the page.

1 Like

@AaronSterling
Thanks for your reply

I did some change in my code

for example :
I init my array in constructor :

 constructor(public navCtrl: NavController, public categories : Categories, public navParams: NavParams ) {
      this.currentCategories = [];
 }

and load my list in ionViewDidLoad .

   ionViewDidLoad() {

         this.categories.query(this.url).subscribe(data => {

                this.currentCategories = data.subCategories || data.elements;
                console.log(data);
            },
            err => {
                console.log(err);
            });
  }

I did that here because I want the result to be cached.

If i wanted to refresh the list if I go back to the page, I would have to use ionViewWillEnter right ?

I don’t really know if it’s better to use OBservable or Promise now… :frowning:

Have you read much about Angular 2? If I had to guess, I’d say you know Javascript and are trying to jump directly to Ionic without Angular background. You might want to step back and learn a bit about Angular’s async pipe, and Observables in general.

@AaronSterling My question was bad formulate :

I know the difference between Promise and Observable and keep this little note with me :

Promises

Definition : Helps you run functions asynchronously, and use their return values (or exceptions) but only once when executed.
Not Lazy
Not cancellable. The two possible decisions are
    Reject
    Resolve
Cannot be retried(Promises should have access to the original function that returned the promise in order to have a retry capability, which is a bad practice)

Observables

Definition : Helps you run functions asynchronously, and use their return values in a continous sequence(multiple times) when executed.
By default, it is Lazy as it emits values when time progresses.
Has a lot of operator which simplifies coding effort. (example : retry, retryWhen...)

But It’s again difficult for me to choose the good one for my implementation ^^
For example here : I was asking me which was better to choose.

But here it’s a simple list not cancelable etc… So maybe use Promise. But If i want to add a loader for example which I can cancel, I have to use Observable. So first of all : Think about all I need ^^

Thanks for your contribution and your answers :wink:

IMHO 95% of the time it really doesn’t matter, so I would recommend just going with whatever the upstream provider is giving you. If it gives you a Promise (like storage), use that. If it gives you an Observable (like Http), use that.

I keep this from a java ^^
Thanks for the advice anyway :wink: