Difference between AngularJS UI Router params object specified in state and views - angularjs

I have just started working on AngularJS and specifically Angular UI Router project. While working on a project I observed that some of team members have specified params option object in view option object of state. when this is the case it doesn't accept optional parameters when passed through ui-sref/state.go.
However I moved this params option object to state instead of view and optional parameters feature started working. I am using AngularJS 1.3.x and AngularJS UI Router version 0.2.13. Here is the sample code to explain more clearly what I want to say :
$stateProvider.state('contacts', {
url:"/user/{userId}/contact"
views: {
'view1': {
....//other options
params :{userId:0,contactId:null}
}
}
...//other options including `controller` and `resolve` options.
});
In above sample code(I have given minimal required information) params object is specified on view1 object instead of on contacts state. Also contactId is the optional non-URL parameter which is passed on one of the use case and not passed in another one. However when I check $stateParams object in the controller specified on state it just shows up userId and not contactId even if I pass it.
I fixed this issue when I moved params option object from view1 object to contacts state object as shown below:
$stateProvider.state('contacts', {
url:"/user/{userId}/contact"
views: {
'view1': {
....//other options
//i have removed the `params` object from here..
}
}
...//other options including `controller` and `resolve` options.
params :{userId:0,contactId:null} //and have put it here.
});
Now I have following questions :
1) What difference does it make by changing where I specify params object. What are the significance if any?
2)Is specifying params object on view altogether wrong configuration? If yes then why UI router doesn't complain and works with parameters specified in URL?
If no then why it doesn't work with optional non-URL parameters?
3) Any specific use cases one would prefer specifying params option object on view object than on state object?
Also another side effect I found when I moved this params option object to state from view object is I am no longer able to bookmark this url or even refresh url in browser. When I do this it redirects me to our home page. Maybe this could be how we are handling this redirection in our project. But just curious to have any pointers why this could be happening?(including how generally this redirection is handled using ui-router) Of course I am going dig deep into our project code to see why this side-effect is happening.
However I would at least like to have answers to my 3 questions(and subquestions) I have asked here.

Neither the guide nor the API documentation say that a named view can have parameters. So I think adding params in the view was just a mistake, and it had no effect whatsoever.
So,
1) What difference does it make by changing where I specify params object. What are the significance if any?
In the views, ui-router doesn't care about it. In the state, it does what is documented in the API documentation.
2) Is specifying params object on view altogether wrong configuration? If yes then why UI router doesn't complain and works with parameters specified in URL? If no then why it doesn't work with optional non-URL parameters?
Yes, it seems to be wrong configuration.
3) Any specific use cases one would prefer specifying params option object on view object than on state object?
No

Related

Multiple optional route parameters and pretty urls with Angular ui router

I am trying to use multiple optional parameters to make urls looks like
/:region/:direction/:subdirection/page/
where all params instead of the last one are optional.
I've tried to use
params:{region: {value: 'default', squash:true}, ...}
for each optional parameter, but when some of them are missed in url, the router doesn't work.
So, the only solution I've found in order to save pretty urls in this situation is to declare multiple routes:
.state('page', {
url: '/:region/page'
}
.state('page-direction', {
url: '/:region/:direction/page'
}
.state('page-subdirection', {
url: '/:region/:direction/:subdirection/page'
}
Additionally:
1. there will be no subdirection without direction,
2. region will be in every link, but it is variable
Are there any optional solutions?
Thnx!
The default parameters are for internal routing, example
$state.go('page-subdirection');
The above will redirect to the state and the $stateParams.region will be the default value you defined for that state.
While $state.go('page-subdirection', {region: 'newValue'); will make $stateParams.region to be newValue in that specific case.
The same apply for constructing the URL from the view:
<a ui-sref="page-subdirection">
<a ui-sref="page-subdirection({region: 'newValue'})">
It may also depend on what your final goal is. From what you're describing, it seems that you may actually be trying to pass in filters into a single state, not necessarily trying to route to 3 different states.
If in the case of filtering a single state, I'd recommend using query parameters as described in the docs (https://github.com/angular-ui/ui-router/wiki/URL-Routing). The advantage is that query parameters are not required or used from a routing point of view, they're simply parameters that your controller will utilize to filter data or tweak the view.
Snippet from above doc link:
Query Parameters
You can also specify parameters as query parameters, following a '?':
url: "/contacts?myParam"
// will match to url of "/contacts?myParam=value"
If you need to have more than one, separate them with an '&':
url: "/contacts?myParam1&myParam2"
// will match to url of "/contacts?myParam1=value1&myParam2=wowcool"

AngularJS: get url path without routeParams

Take this route for exmaple
when('/coordinator/editApplications/:appId', {
templateUrl: 'assets/app/templates/coordinator/editApplications.tpl.html',
module: "/coordinator",
})
Without using regular expressions, is there a property/method available in Angular that will allow me to get the path value with the parameters stripped off?
The value I would want for this example would be /coordinator/editApplications
This needs to be be universal because there could be multiple params or differently named params. I can't find anyway on the $route or $location to get this value as they all seem to contain the params.
Again, I know i can use regExp to do this but I want to avoid that. I also don't want to just add another property to the route w/ the non-param url value.

Dynamic view names with ui-router

I am trying to target dynamic named views in an ng-repeat but can't do so at config phase as views can only be named statically. Is there a way imitate url param matching like '/path/:param' but with view names like views: {'path:param': {...}} ?
I've tried modifying the state config object at run() to see if changing state configuration after config() had any effect:
rootScope.$on('$stateChangeStart', function(e, to, toP, from, fromP) {
//nope
if(toP.itemId) {
to.views['item-'+toP.itemId+'#home'] = to.views['item-:itemId#home'];
delete to.views['item-:itemId#home'];
}
}
plunker: http://plnkr.co/edit/ZkrteD1ls71yd5V10Xub?p=preview
This concept would not be working, in general.
The reason is that stable, solid states should not be driven by the data (which are very dynamic, changing frequently). All states and their views :{} should be defined first. The data (as a list of items) should be injected there, consuming already defined states.
states should be defined once (even if a bit later, once configuration is loaded via $http)
data could change during the application life-time often, frequently. They should be placed into states/views - but not drive them
How to load dynamic states dynamically with $http (using the .run() phase)? Check these with full examples and details:
AngularJs UI-Router - Page Refresh $state.current is now empty
AngularJS - UI-router - How to configure dynamic views
the doc: $urlRouterProvider.deferIntercept(defer)
Small extract from the doc of deferIntercept(defer):
Disables (or enables) deferring location change interception...
So, we can (once) postpone the url / location handling... to the moment, when all states are dynamically loaded. But this feature could be used just once.
Well - all that could still not fit into what we want - place some details into the list.
There is a big detail Q & A, which should give some insight:
How to replace list item with details
Please, have a look at that, because there is detailed explanation and working example...

How to hide stateProvider url displayed in Address bar using Angular JS?

All,
I am using Angular JS 1.3.0 stateProvider URL for URL routing.
During run time whenever state is being redirected to particular URL , it displayed on the Address bar and it exposes the information about Employee id. Like in this image.
Is it possible to hide those potential information using Angular JS 1.3.0?
The personId is displayed in the url, because its defined as URL parameter.
But we can avoid that, by defining it with params notation:
.state("peopleDetail", {
url : "/",
params : { personId : null },
...
}
Check the doc:
$stateProvider
A map which optionally configures parameters declared in the url, or defines additional non-url parameters. For each parameter being configured, add a configuration object keyed to the name of the parameter.
...
Each parameter configuration object may contain the following properties:
value
array
squash -- (see more in that resource)
For similar stuff and some more details, please check:
Angular ui router passing data between states without URL

Whats the Advantage of Marionette AppRouter+Controller over Backbone.Router?

From my understanding, the differences is the callback functions to events on an AppRouter should exist in the Controller, instead of the same Router object. Also there is a one-to-one relationship between such AppRouter & Controllers, all my code from Router now moves to Controller, I don't see too much point of that? So why use them? I must be missing something?
The way I see it is to separate concerns:
the controller actually does the work (assembling the data, instanciating the view, displaying them in regions, etc.), and can update the URL to reflect the application's state (e.g. displayed content)
the router simply triggers the controller action based on the URL that has been entered in the address bar
So basically, if you're on your app's starting page, it should work fine without needing any routers: your actions (e.g. clicking on a menu entry) simply fire the various controller actions.
Then, you add on a router saying "if this URL is called, execute this controller action". And within your controller you update the displayed URL with navigate("my_url_goes_here"). Notice you do NOT pass trigger: true.
For more info, check out Derick's blog post http://lostechies.com/derickbailey/2011/08/28/dont-execute-a-backbone-js-route-handler-from-your-code/ (paragraph "The “AHA!” Moment Regarding Router.Navigate’s Second Argument")
I've also covered the topic in more length in the free preview of my book on Marionette. See pages 32-46 here: http://samples.leanpub.com/marionette-gentle-introduction-sample.pdf
I made some override for the router. And currently use it in this way (like Chaplin):
https://gist.github.com/vermilion1/5525972
appRoutes : {
// route : controller#method
'search' : 'search#search'
'*any' : 'common#notFound'
},
initialize : function () {
this.common = new Common();
this.search = new Search();
}

Resources