Multiple $stateParams causing controller to be called multiple times - angularjs

I have a stateProvider which looks like:
$stateProvider.state('test.example', {
url: '/test?param1&param2',
templateUrl: 'test/testParam.html',
controller: 'testParamCtrl'
});
When I console log $stateParams in my controller, it runs twice. This happens only when I'm switching between tabs on my app. This problem doesn't occur if I refresh the app.
It seems as if the controller is "building" the stateParams object and instantiating the controller each time. Therefore, I'm getting some angular errors of param2 being undefined during the first instantiation. This is what the console logs look like:
Object {param1: "data1", param2: undefined} // first instantiation
Object {param1: "data1", param2: "data2"} // second instantiation
When I refresh the page, however, only one console log shows up, which is the "correct one" (i.e. param1 and param2 are both defined).
Thanks in advance!

My guess is that in 'test/testParam.html' you have ng-controller="testParamCtrl". Remove ng-controller in the template or remove the controller property in your state definition.

I think you need to change your state defination to:
$stateProvider.state('test.example', {
url: '/test/:param1/:param2',
templateUrl: 'test/testParam.html',
controller: 'testParamCtrl'
});
to pass parameters in the right way.

You need to assign parameter values
$stateProvider.state('test.example', {
url: '/test/:param1/:param2',
params: {
param1: "data1",
param2: "data2" }
templateUrl: 'test/testParam.html',
controller: 'testParamCtrl'});

Related

Angular UI Router Wrong Template And Controller

I have an odd issue where I use an ng-click to $state.go() to a state, and get the correct url but the wrong template and controller.
These are my states:
app.config(function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise("/messages");
$stateProvider.state('message', {
url: "/messages/:to/:fro/:messageID",
templateUrl: 'message.html',
controller: 'MessageCtrl'
}).state('compose', {
url: "/messages/compose/a/message",
templateUrl: 'compose.html',
controller: 'ComposeCtrl'
});
});
This is the function triggered by my ng-click and I am in fact getting the console log so I know the right one is firing.
$scope.composeMe = function(){
console.log("You want to compose a message!");
$state.go("compose");
};
When I fire that function I get the url to change to http://example.com/messages/compose/a/message but I get the templateUrl and the controller of the message state.
Why is that? The other state is fired from a similar (ng-click derived) function and works perfectly.
The URL you are trying to go to matches the one you are actually going to.
How would ui-router know that "compose" isn't the to: field you want, "a" isn't the fro: field you want, and "message" isn't the messageID you want?
Move the more specific state definition above the one with URL parameters.

Can i use ui-sref to call ui-router state using URL and parameters?

we have three pages in our app which can be classified under one parent page as below.
1)Parent
I)Child1
II)Child2
III)ChildIII
.state('Parent', {
url: '/Parent/:ID',
templateUrl: 'parent.html',
controller:'parentcontroller'
})
.state('Parent.Child1', {
url: '/Child1',
templateUrl: 'Child1.html'
})
.state('Parent.Child2', {
url: '/Child2',
templateUrl: 'Child2.html'
})
.state('Parent.Child3', {
url: '/Child3',
templateUrl: 'Child3.html'
})
sometimes we need to call this child pages sequentially one after another from child1 to child3 without parameters and sometimes we need to call those child pages individually but requests needs to go through parent controller so that we do not have to instantiate new controller instance for each one of those child pages. to accomplish this i'm using href but i want to be able to call parent and child with out passing any params.
working href ex: <a href='../Parent/{{ID}}/child1'
Not working ex: <a href='../Parent/child1'
can anyone please guide me to accomplish this?? Thanks!!
solution:
.state('Parent', {
url: '/Parent/:ID',
templateUrl: 'parent.html',
controller:'parentcontroller',
params:{ID:null}
})
.state('Parent.Child1', {
url: '/Child1',
templateUrl: 'Child1.html'
})
.state('Parent.Child2', {
url: '/Child2',
templateUrl: 'Child2.html'
})
.state('Parent.Child3', {
url: '/Child3',
templateUrl: 'Child3.html'
})
From HTML:<a ui-sref="(Parent.Child1{ID:{{value}}})">Home</a>
i wasn't aware that if we use SREF as above and controller declared at parent value can still read the params but gave a shot and it worked!!
Yes, you can do this. First you should define your params in your .state(), if you are passing params to child1 state, then it should defined by like below,
.state('Parent.Child1', {
url: '/Child1',
templateUrl: 'Child1.html',
params: {
paramName: '' //here paramName can be named by your wish.
}
})
after this you should pass the call the state and pass param in ui-sref like below,
<a ui-sref="Parent.Child1({paramName: scopeName})">Click</a>
here scopeName is the name of the scope which have the value to param, if you want hard code a string, then you can pass in qoutes, ({paramName: 'some string'})
I'm a little confused about what you're asking, but the way it sounds is that all the pages use the same controller. If that's the case, just let them. Controllers will eventually be destroyed when they are no longer needed, so instantiating a new one is fine. If you're routing to a new page, it's going to look for the accompanying controller.
--Edit based on OP's comment--
If the goal is to only get data once, you can store that in a service. Every service is a singleton, so if you grab data and save it in your service, you can inject that service elsewhere and have access to it.

How to modifiy a variable inside a $stateParams object from the controller?

I want to get the value of one of the properties in the $stateParams object in my controller. I seem to be able to get the $stateParams object as a whole but I can't get a specific property.
$rootScope.params = $stateParams; // this gets me the object
$rootScope.myVar = $stateParams.fooParam + ' some msg'; // this gets me undefined
So this is how I setup my $stateProvider...
$stateProvider
.state('parent', {
url: "/parent",
templateUrl: 'tpl.html',
params: {
fooParam: 'foo defult',
barParam: 'bar defult'
},
controller: 'ParentCtrl'
})
And then in my html ui-sref route, I pass some stuff to the param.
<a ui-sref="parent({
fooParam:'foo parent',
barParam:'bar parent'
})">parent</a>
Then in my controller I want to access those params. Here is where Is truggle to access members of the $stateParams object.
$rootScope.myVar = $stateParams.fooParam + ' some msg';
In my HTML if I call {{myVar}}, I just get "undefined some msg"
Basically in this particular example I want to get the value of the fooParam in my controller. I don't understand how to do that.
Here's a Plunker of the example of my issue:
https://plnkr.co/edit/dXTgKMpBTHiv2Bt5nFxC?p=preview
Actually, I was wrong. You do need to include params in the url as below:
$stateProvider
.state('parent', {
url: "/parent/:fooParam/:barParam",
params: {
fooParam: 'foo defult',
barParam: 'bar defult'
},
templateUrl: 'tpl.html',
controller: 'ParentCtrl'
})
But the other issue is that you need to access $stateParams from the controller registered for that state, which is listed in the gotchas section of the documentation.
See updated plunker showing myVar from $stateParams injected in controller (works fine) and MyVar2 from $stateParams injected in app.run() function (doesn't work).
You can inject $stateParams directly into controller. Change your controller as below.
.controller('ParentCtrl', ['$scope','$stateParams', function($scope,$stateParams)
Here is the Plunker
https://plnkr.co/edit/PVXGjFLMVQdvxUHp1rgs?p=preview

Angularjs ui-router - pass extras 'unplanned' parameters

I have this simple state :
.state('search', {
url: '/search',
templateUrl: 'views/search.html',
controller: 'search'
})
And I would like to pass any extra unplanned parameters to the controller when using search state or /search route :
ui-sref="search({foo:1, bar:2})"
// would call '#/search?foo=1&bar2',
// match the state and pass foo and bar to the controller (through $stateParams)
When I try this, it matches the otherwise of the router instead. :(
I've read a lot of solutions that imply to declare each parameter in the state:
.state('search', {
url: '/search?param1&param2&param3?...',
})
But I cannot do this as far as the parameters list is not really defined and changes all the time depending on searched content.
Is there a way to achieve this ? Or am I wrong somewhere ?
Thx.
EDIT : When I try to call directly this url : #/search?foo=1, the state search matches but the foo parameter never goes to $stateParams which is empty. I don't know how to get it in.
.state('search', {
params: ['param1','param2','param3'],
templateUrl: '...',
controller: '...'
});
ui-sref="search({param1:1, param2:2})"
Credit goes to Parameters for states without URLs in ui-router for AngularJS

Angularjs: Reload on path change but not search parameters

$stateProvider.state('search-results', {
url: '/s/:path?param1&param2&param3',
controller: '...Controller',
templateUrl: '....html',
reloadOnSearch:false
});
Now I want the controller not to load when there is change in the param1, param2 or param3. But I want controller to load when there is change in the path.
When I do
$state.go('search-results', {
path: "path",
param1: "param1",
param2: "param2",
param3: "param3"
})
With a new path, the controller doesn't reload. Infact the URL also deosn't change. I can get around the URL problem by using $location. But in that case also the controller is not reloaded.
Note: I found some similar questions, but since I am using $state instead of $route, my question is different.

Resources