Reputation: 248
I'm migrating my app to ui-router 1.0.0 and I have this issue with nested states, when onEnter $transitions hook fires as many times, as many parents the state has (i.e. how deep it is nested), regardless of whether I filter states in my hook or not. Is this expected or a bug?
$stateProvider
.state("root", {
url: "/"
})
.state("root.child", {
url: "/child"
})
.state("root.child.child", {
url: "/child",
data: {
foo: "bar"
}
});
$transitions.onEnter(
{to: state => state.data && state.data.foo === "bar"},
transition =>
console.log(`on enter triggered`, transition.from(), transition.to())
);
$state.go("root.child.child");
In this example the hook is fired 3 times.
Here's the fiddle.
Upvotes: 1
Views: 963
Reputation: 248
I created an issue on github with same question, and christopherthielen, the top contributor of the ui-router gave me a comprehensive answer to this question, which I'm obliged to post here in case someone comes across the same problem.
This is expected based on how you coded your hook. The onEnter
hook is a state based. The pseudocode for processing onEnter
is as follows:
When initially going to root.child.child
there are three states being entered: root
, root.child
, root.child.child
.
Your criteria is { to: state => state.data && state.data.foo === "bar" }
which matches for each of the three states being entered. This is because although three states are being entered, there is only one "to state", which is root.child.child
. That state's data has the foo: 'bar'
data, so it matches.
You should change your criteria to use entering
instead of to
.
{ entering: state => state.data && state.data.foo === 'bar' }
Here's an updated fiddle: https://jsfiddle.net/2m63pvqb/1/
Some other approaches that might work:
Put onEnter
on the state itself
.state("root.child.child", {
url: "/child",
data: {
foo: "bar"
},
onEnter: ($transition$, $state$) => do something specific when entering root.child.child
});
do something ONCE per transition if any states being entered have data.foo === 'bar'
$transitions.onStart({ entering: state => state.data && state.data.foo === 'bar' }, trans =>
// do something
Upvotes: 1
Reputation: 62
Use the app.js for checking if the enterbutton hitted. There u can insert a function like $rootScope.hitEnter = function(){ });
in the run-area. That should work better then in the config-area.
Upvotes: 0