$stateChangeSuccess getting hit twice - angularjs

I have an $http call that is made inside of a function getRoutes that fires off whenever that state has changed:
$scope.$on('$stateChangeSuccess', function(event) {
$scope.getRoutes($stateParams);
})
I have another function that changes a state parameter and then calls $state.go():
$scope.bindSelectedRoute = function(){
$stateParams.pickup_route= this.d.pickup_route;
$state.go('track.search', $stateParams);
}
My problem is that the http call keeps being made twice. First with the $stateParams correct and then a second call with an empty object getting passed. I'm assuming this is a core part of angular that I'm missing.
Any hints?
Best.

I can't suggest refactored code for you but I believe the answer is because you did a $state.go(). You already told the app to fire $scope.getRoutes($stateParams) when the stateChangeSuccess is fired so when $state.go() fires and it successfully changes the state, $scope.getRoutes($stateParams) gets fired again.

Related

virtual dom and real dom issue while changing state

i am calling console.log just below the setState but it showing my blank array even state has been changed.
let text = reminderText;
let data = [...this.state.reminderText]
data.push(text);
this.setState({reminderText:data})
console.log(this.state.reminderText);
Note that setState() is asynchronous. That means, when your console log is executed, the state is not updated yet.
If you want to print the updated state, use the callback function as shown below.
this.setState(
{reminderText:data},
() => console.log(this.state.reminderText)
)
React will invoke the callback function soon after the asynchronous state update is complete.

How to execute onEnter after the onExit api call callback

I call an API on every OnEnter to retrieve the state of my data.
The state of the data is updated on every OnExit by calling a POST on API.
So the test of my state is always late from one state, because the call on the API to retrieve data is called before the save on the State from the onExit.
My question is how to run OnEnter from the OnExit api call callback ?
Thanks
Save the onExit promise and chain the onEnter from it.
var promise = restangularAPI.post();
promise.then ( function () {
restangularAPI.get();
});
If the post has already completed the get will execute immediately. Otherwise the $q service will wait for the post to complete before executing the get.

ui-router: Do controllers ever get destroyed after transitions?

I am using ui-router and am trying to detect when a controller belonging to a view that's being transitioned away from gets destroyed.
So I currently have a destroy listener like so:
$scope.$on('destroy', function(){
mySpecialFunction();
});
However, when a state change occurs to a different view\controller, this destroy event never fires.
The state I am transitioning to, is a sibling state so I'm going from myParent.childA to myParent.childB (where childA has the destroy listener added).
If I was instead going from myParent.childA to myParent.childA.child1 then this would make sense since childA still exists in the hierarchy.
Can someone help me understand why the scope still exists in this scenario please?
The event name you want is "$destroy" not "destroy"
Try
$scope.$on('$destroy', function(){
mySpecialFunction();
});
This should get triggered under the conditions mentioned in question

AngularJS scope not updating

After executing get or put in indexeddb, the callback is updating the scope.
The problem is, no update is being triggered in the ui!
A common solution is to use apply or digest but that is wrong, you should NOT use those operations. Angular should update it automatically.
Now my guess, after reading some stuff, is that the callback is being executed in a different context, outside of the scope.
My question is basically: how can I execute an indexeddb callback in an angularjs scope context?
EDIT:
A rough look on how its built:
GetObjectStoreData(iDb, objectStore, function (res) {
$scope.result = res;
}
The call is made from inside the scope so the scope is used in the callback. The callback parameter is the contents of the object store
You asserted that you should not have to use Scope.$apply because AngularJS should do it for you.
This is true only for callbacks managed by Angular. For example, when you use $timeout in place of window.setTimeout, angular wraps your provided callback in a call to Scope.$apply, causing a digest cycle to run once your callback completes. If you interact directly with browser APIs rather than calling through AngularJS, it is your responsibility to call Scope.$apply at the appropriate time.
If you don't want to manage the scope directly, you could instead use a wrapper library like angular-indexedDB, which (amongst other things) handles the scope notifications when callbacks occur.

Prevent all $state transitions until promise is resolved

I am using ui-router.
I want to be able to block any state transitions until a promise is resolved.
There's are multiple states, so setting the same resolve property on all is not a good idea.
The promise needs to be resolved inside the Angular app, so bootstrapping the app after an external promise is resolved won't work.
My current solution relies on having a $stateChangeStart listener that calls event.preventDefault(); and which removes itself after the promise is resolved. There are many complications with this solution besides the fact that its intention isn't clear unless well commented.
So, is there a better solution to block all state transitions until everything's cool?
Create one abstract parent state, make the rest children of that state. Use the resolve object on the parent state so it's resulting dependency will be available to all child states.
See: https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views#abstract-states
An abstract state can have child states but can not get activated itself. An 'abstract' state is simply a state that can't be transitioned to. It is activated implicitly when one of its descendants are activated.
Some examples of how you might use an abstract state are:
To provide resolved dependencies via resolve for use by child states.
I think you want to use $urlRouterProvider.deferIntercept()
See here: http://angular-ui.github.io/ui-router/site/#/api/ui.router.router.$urlRouterProvider
app.config(function ($urlRouterProvider) {
$urlRouterProvider.deferIntercept();
};
app.run(function($urlRouter, myservice) {
myservice.promise.then(function() {
$urlRouter.listen();
$urlRouter.sync(); // not sure if this is necessary
});
});

Resources