calling controller function from within a promise

2019-08-15 02:40发布

问题:

Ionic Tabs, root of tabs HTML has "RootTabCtrl", and "Tab1" (with "Tab1_Ctrl") has a form, other tabs are disabled.

  1. User submits form on Tab1
  2. Tab1 Controller function kicks off.
  3. Controller Function calls an external function (not in controller).
  4. External function triggers, which executes a promise
  5. In promise "results", returned data is processed
  6. If X in returned data is true, trigger "RootTabCtrl" function to enable the other disabled tabs.
  7. I can track console messages triggering every step of the way.

This all works except for this following odd behavior. "RootTabCtrl" doesn't enable the disabled tabs until the user clicks the form submit a second time...even though I see console messages saying it is in (at the end) of the RootTabCtrl function. I see all the same console messages from the first click - but on the 2nd time is when the disabled tabs get enabled again.

If I move step 6 outside of the promise in Step 4, and put it after step 3 (and before the promise), then all the tabs get enabled on the 1st click. However, this is no longer taking into account the value of X to determine if other tabs should be re-enabled or not.

What can I look for, or am not aware of, that would be causing this?

app.js:

 .state('tab', {
    url: "/tab",
    abstract: true,
    templateUrl: "templates/tabs.html",
    controller: 'TabsCtrl'
  })

  // Each tab has its own nav history stack:

  .state('tab.tab1', {
    url: '/map',
    views: {
      'tab-1': {
        templateUrl: 'templates/tab-1.html',
        controller: 'tab1Ctrl'
      }
    }
  })

controllers:

.controller('TabsCtrl', function($scope,$rootScope,constants) {
  $scope.constants = constants ;
  $scope.tabControl = { 
    disableRides : true,
    disableBikes : true,
    disableTransit : true
  }

  var refreshFinalizer = $rootScope.$on('updateTabsRefresh', function (event, data) {
    console.log("Refresher 1") ;
     $scope.tabControl.disableTab2 = false;
     $scope.tabControl.disableTab3 = false ;
     console.log("Refresher 2") ;
  });

  $scope.$on('$destroy', function () {
    console.log("Destroy") ;
    refreshFinalizer ();
  });
})

.controller('tab1Ctrl', function($scope,$rootScope) {

  $scope.setInfo= function() {
    getGoogle(document.getElementById('form_data').value,0);
  }
  $scope.enableTabs = function(type) {
    console.log("Here enableTabs1") ;
    $rootScope.$broadcast('updateTabsRefresh');
    console.log("Here enableTabs2") ;    
  }
})

Tab1 has a form, upon click, it executes $scope.setInfo. Then getGoogle() is in an outside JS function, its a call to google maps, and if specific data X is true, then enable all the other tabs using tab1Ctrl $scope.enableTabs() :

    function getGoogle(userInfo,clear) {
        console.log("setInfo 1") ;
        geoCoder.geocode({'address': userInfo}, function(results, status) {
          if (status == google.maps.GeocoderStatus.OK) {
            if (results[0]) {
              // extra code removed
              startPointSet = 1;
           // tab1Ctrl html has id of "Tab1" 
angular.element(document.getElementById('Tab1')).scope().enableTabs();
              /* alternative method, worked the same as previous line but with same problem 
              var $sBody = angular.element(document.body) ;
              var $sRootScope = $sBody.injector().get('$rootScope') ;
              $sRootScope.$broadcast('updateTabsRefresh') ;
              */
              console.log("setInfo 2") ;
            }
          } else {
            // extra code removed
            console.log(response) ;
          }
        });
      }
    }

All of the above works...except that when the call to enableTabs (within the google response), even though it correctly calls enableTabs and I can see the console.log messages firing from within enableTabs - the other tabs don't "enable" until the form button is clicked a 2nd time (and then I see all the console messages again). I tried 2 different methods, from within getGoogle(), both worked exactly the same - 1st clicked fired all functions correctly, but tabs did not enable. 2nd click fired all the functions and then the tabs got enabled.

回答1:

Try this previous answer. Are you using $http calls? If so I have never actually had to do that so it seems like something else might be the root cause.

UPDATE

How about creating an Angular Service for this GetGoogle function call. Then you will still be inside of angular and can inject $rootScope and anything else that you need. You will need to inject this service into your tab1Ctrl (the myGoggleService below). I would also probably just pass the form back on the ng-submit:

Html

ng-submit="setInfo(formNameGoesHere)"

Controller

.controller('tab1Ctrl', function($scope, $rootScope, myGoogleService) {
    $scope.setInfo = function(form) {
        myGoogleService.getGoogle(form);
    }
    $scope.enableTabs = function(type) {
        console.log("Here enableTabs1");
        $rootScope.$broadcast('updateTabsRefresh');
        console.log("Here enableTabs2");
    }
});

Service: If you haven't created any already you will need to register it in your app.js like any directives you have and also put them in your index.html page like a regular controller.

.service('myGoggleService', [ '$rootScope', function ($rootScope) {
  this.getGoogle = function(userInfo,clear) {
    console.log("setInfo 1") ;
    geoCoder.geocode({'address': userInfo}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            $rootScope.$broadcast("updateTabsRefresh");
        } else {

        }
    });
  }
}}]);

I did copy your code from above and then just removed some of the extra stuff just to get the point across. Obviously could not run the code so there might be some mistakes or slight changes needed, but hopefully this will get you close.