Home > Enterprise >  Ionic run function AFTER html has loaded and AFTER api call
Ionic run function AFTER html has loaded and AFTER api call

Time:09-25

I have a function called getPuzzle() that calls an API to get data. I want to use that data to modify a div. The issue is that this is all done in the constructor and so the html hasn't been loaded yet.

So I put the code that modifys the html into ionViewDidEnter, however then it runs before the call to the API and it's missing the data this.puzzle

How do I not run this code until the HTML has loaded completely and AFTER the API call?

ngOnInit() {
    this.getPuzzle();
  }

getPuzzle() {
      //Get puzzle info
      this.puzzlesService.getPuzzle().subscribe((data) => {
        this.puzzleType = this.puzzlesService.puzzleType;
        this.puzzle = this.puzzlesService.puzzle;
      });
  }

ionViewDidEnter() {
    //Set first tab
    if (this.puzzleType == 'text') {
      new Vara("#text", "assets/fonts/vara/Satisfy/SatisfySL.json", [{
        text: this.puzzle,
        delay: 2000,
        x: 2
      }], {
        fontSize: 25,
        strokeWidth: 1.5,
        duration: 15000,
        color: "black"
      });
    }

  }

CodePudding user response:

Quick Solution

This is pretty deep into the well of trying to use RxJS imperatively instead of decoratively (Which is a pretty major code-smell with RxJS). Even so, this is one way to ensure that this.puzzlesService.getPuzzle() inside getPuzzle has emitted before the code after //Set first tab is run.

letsGooooooo = new ReplaySubject();

ngOnInit() {
  this.getPuzzle();
}

getPuzzle() {
  //Get puzzle info
  this.puzzlesService.getPuzzle().subscribe((data) => {
    this.puzzleType = this.puzzlesService.puzzleType;
    this.puzzle = this.puzzlesService.puzzle;

    this.letsGooooooo.next("GOOOOOOO!");

  });
}

ionViewDidEnter() {

  this.letsGooooooo.pipe(
    take(1)
  ).subscribe(_ => {
    //Set first tab
    if (this.puzzleType == 'text') {
      new Vara(
        '#text',
        'assets/fonts/vara/Satisfy/SatisfySL.json',
        [
          {
            text: this.puzzle,
            delay: 2000,
            x: 2,
          },
        ],
        {
          fontSize: 25,
          strokeWidth: 1.5,
          duration: 15000,
          color: 'black',
        }
      );
    }
  });
  
}

More Involved Solution

Fix your service so that puzzlesService cashes the current puzzle and puzzle type as an observable rather than properties. Then you don't need to re-implement all those functions locally.

ngOnInit() {
  // No local version of puzzlesService needed
}

ionViewDidEnter() {

  this.puzzlesService.getPuzzle().subscribe(puzzleData => {
    //Set first tab
    if (puzzleData.puzzleType == 'text') { // puzzleData.puzzleType instead of this.puzzleType
      new Vara(
        '#text',
        'assets/fonts/vara/Satisfy/SatisfySL.json',
        [
          {
            text: puzzleData.puzzle, // puzzleData.puzzle instead of this.puzzle
            delay: 2000,
            x: 2,
          },
        ],
        {
          fontSize: 25,
          strokeWidth: 1.5,
          duration: 15000,
          color: 'black',
        }
      );
    }
  });
  
}

CodePudding user response:

You are facing lifecycle issues. So, the best that you can use is ngAfterViewInit();

ngAfterViewInit() {
  this.getPuzzle();
}
  • Related