0

I have a very interesting problem with my fragment of app code.

CategoriesPageComponent:

export class CategoriesPageComponent implements OnInit {

  private categories: Array<Category> = [];
  public randomizedCategories: Array<Category> = [];

  constructor(private router: Router,
              private categoriesService: CategoriesService){


    this.categoriesService.getAllCategories().subscribe((categories) => {
      this.categories = categories;
      this.randomizedCategories = this.randomizeCategories(this.categories, 7);
    });
  }

  ngOnInit() {
  }

  private randomizeCategories(allCategories, numberOfCategories): Array<Category> {
    const categoryArray = [];
    const categoriesIDsArray = this.getRandomArray(1, allCategories.length - 1, numberOfCategories);

    for (var categoryKey in categoriesIDsArray) {

      const subcategoryID = this.getRandomArray(1, allCategories[categoriesIDsArray[categoryKey]].subcategories.length - 1, 1);

      console.log(subcategoryID);
      const wordID = this.getRandomArray(1, allCategories[categoriesIDsArray[categoryKey]].subcategories[subcategoryID].words.length - 1, 1);

      const word: Word[] = allCategories[categoriesIDsArray[categoryKey]].subcategories[subcategoryID].words[wordID];
      const subcategory: Subcategory[] = allCategories[categoriesIDsArray[categoryKey]].subcategories[subcategoryID];
      subcategory['words'] = word;

      const category: Category = allCategories[categoriesIDsArray[categoryKey]];
      category.subcategories = subcategory;

      categoryArray.push(category);
    }

    return categoryArray;
  }

  getRandomArray(min, max, numOfElements) {
    let A = [];
    while (max >= min) {
      A.push(max--);
    }

    A.sort(function () {
      return .5 - Math.random();
    });
    return (numOfElements === 1) ? A[0] : A.slice(0, numOfElements);
  }

  changeCategories(){
    console.log(this.randomizeCategories(this.categories, 7));
  }
}

When the randomizeCategories() methods are executed in the constructor all run very well, but when I have called this method in changeCategories() method when I clicked the button, in the browser's console is throwing the error:

Picture with error

The 49 line of code is:

  const wordID = this.getRandomArray(1, allCategories[categoriesIDsArray[categoryKey]].subcategories[subcategoryID].words.length - 1, 1);

wordID, subcategoryID variables are undefined.

Do you have any idea to resolve this problem?

Thank you for help in advance.

2
  • Try to console.log this.randomizedCategories and this.categories in the ngOnInit() method Commented May 5, 2018 at 22:36
  • The arrays are empty, because subcribe method is will execute after ngOnInit() Commented May 6, 2018 at 11:02

1 Answer 1

1

in this case you call the method before the observable is resolved so the array is empty and face error.

For solving this problem you should wait till the the array is filled, so in html try:

<button *ngIf="categories?.length">...</button>

so that the part within the <button> is not rendered before the data is available or use (as I have already in the *ngIf) the safe-navigation operator. ?. This way the property after .? is only evaluated when the categories is != null.

Sign up to request clarification or add additional context in comments.

2 Comments

Okay I add yout fragment of code to my html document, the button is showing after the this.categories is no empty, but the problem is the same . . . when i try call console.log(this.categories) in randomizeCategories() the this.categories array is not null, so it should work very well. At the beginnig I think that i modify the this.cateories array by the reference, but i don't modify data on this array (read only).
you mention this code in subscribe and it works after the observable is resolved and the array is full, but when you call changeCategories() from button the observable is still fetching data and not resolved yet, so the array in console is showed something like test:[] and get full after the observable is resolved.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.