angularjsionic-frameworksettimeoutpopoverionic-v1

Angular/Ionic code calling functions not yet loaded


Took me forever to figure out what was happening. A standard $ionicPopover was being called and I was getting a

Cannot read property 'show' of undefined

As soon as the controller is entered its checking for a $stateParm - if set, then launch the popover. The problem though is the $ionicPopover template wasn't loaded into the $scope yet so $scope.popover.show() was returning the error.

When I added a setTimeout(function() { $scope.popover.show(); },2000) ; - that delayed things long enough for the popover to be loaded into the scope and allowed it launch.

Even though this bandaid works, I don't like using this method. What other method can I use to ensure the $ionicPopover/$ionicModal are all loaded other code is allowed to execute and reference them?

  $ionicPopover.fromTemplateUrl('pushPopover.html', {
    scope: $scope,
    focusFirstInput:false
  }).then(function(popover) {
    $scope.popover = popover;
  });

  $scope.openPopover = function() {
    $scope.popover.show();  // calls before popover is loaded causing error
  }
  $scope.closePopover = function() {
    $scope.popover.hide();
  }
  if ($stateParams.pushAction == 1) {
    $scope.pushSub = $stateParams.pushSub ;
    $scope.pushMsg = $stateParams.pushMsg ;
    $scope.pushCode = $stateParams.pushCode ; 
    $scope.openPopover() ;  
  }  

In order to get it work, I have to intentionally delay the call with a sloppy timeout:

  if ($stateParams.pushAction == 1) {
    $scope.pushSub = $stateParams.pushSub ;
    $scope.pushMsg = $stateParams.pushMsg ;
    $scope.pushCode = $stateParams.pushCode ; 
    setTimeout(function() {
      $scope.openPopover() ;
    },2000) ;
  }  

Solution

  • One technique is to store the promise and chain from it:

    var popoverPromise = $ionicPopover.fromTemplateUrl(
      'pushPopover.html',
      {
        scope: $scope,
        focusFirstInput:false
    });
    
    popoverPromise.then(function(popover) {     
        $scope.popover = popover;
    });
    
    $scope.openPopover = function() {
        ̶$̶s̶c̶o̶p̶e̶.̶p̶o̶p̶o̶v̶e̶r̶.̶s̶h̶o̶w̶(̶)̶;̶ ̶ ̶/̶/̶ ̶c̶a̶l̶l̶s̶ ̶b̶e̶f̶o̶r̶e̶ ̶p̶o̶p̶o̶v̶e̶r̶ ̶i̶s̶ ̶l̶o̶a̶d̶e̶d̶ ̶c̶a̶u̶s̶i̶n̶g̶ ̶e̶r̶r̶o̶r̶
        popoverPromise.then(function(popover) (
            popover.show(); //called after popover loaded
        }); 
    };
    
    $scope.closePopover = function() {
        ̶$̶s̶c̶o̶p̶e̶.̶p̶o̶p̶o̶v̶e̶r̶.̶s̶h̶o̶w̶(̶)̶;̶
        popoverPromise.then(function(popover) {
            popover.hide();
        });
    };
    

    Services immediately return promises while .then blocks wait for data from the server.