Get the context, angular, ui-router, nothing special, a root view built with 3 named ui-views.
so in index.html we have
<body>
<div ui-view='left'>
<div ui-view='center'>
<div ui-view='right'>
</body>
my route looks like
$stateProvider
.state('main', {
url: '/',
views: {
'left': {templateUrl: 'foo.html'},
'center': {templateUrl: 'bar.html'},
'right': {templateUrl: 'xyz.html'}
}
})
.state('main.b', {
url: '/b',
params: { foo: {value: 'bar'} }
views: { 'right#': {templateUrl: '123.html'} } // I wish to update $stateParams in 'left#' view
})
.state('main.c', {
url: '/c',
params: ...
views: { 'left#': ..., 'center#': ..., 'right#': .. }
});
Is there a way in going to b state to update the $stateParams in the 'center' and 'left' view?? I can get it using a service but i need to add a $watch to the variable I need and it looks a little bit hacky to me.
Going into c state I can actually get what I want, but the view is reloaded, and i wish to avoid this behaviour cause i have a canvas in the 'left' view.
You could use the following to go to a specific route without reloading the views:
$state.go('.', {parm1: 1}, {notify: false});
The last object literal represents the options which you can pass along to go. If you set notify to false, this will actually prevent the controllers from being reinitialized. The . at the beginning is the absolute state name or relative state path you wanna go to.
The important thing is the notify though.
I think that using "Dynamic params" is now a better solution:
When dynamic is true, changes to the parameter value will not cause the state to be entered/exited. The resolves will not be re-fetched, nor will views be reloaded.
$stateProvider.state('search', {
url: '/search?city&startDate&endDate',
templateUrl: 'some/url/template.html',
params: {
city: {
value: 'Boston',
dynamic: true
}
}
}
and then:
$state.go('.', {city: 'London'});
https://ui-router.github.io/ng1/docs/latest/interfaces/params.paramdeclaration.html#dynamic
https://github.com/angular-ui/ui-router/issues/2709
Quoting #christopherthielen from https://github.com/angular-ui/ui-router/issues/1758#issuecomment-205060258:
using notify: false is almost never a good idea, and is now
deprecated. Use reloadOnSearch if you must.
You can also try dynamic parameters in the 1.0 version (currently
1.0.0-alpha.3). In your state, configure a parameter as dynamic and implement the uiOnParamsChanged callback :
.state('foo', {
url: '/:fooId',
params: { fooId: { dynamic: true } },
controller: function() {
this.uiOnParamsChanged = function(changedParams, $transition$) {
// do something with the changed params
// you can inspect $transition$ to see the what triggered the dynamic params change.
}
}
});
For a demo, have a look at this plunker: http://plnkr.co/edit/T2scUAq0ljnZhPqkIshB?p=preview
Related
How can I refresh the 'detail' state without refreshing its parent (item).
in routes:
$stateProvider.state('item.detail', {
url: '/:id/detail',
abstract: true,
resolve: {
$modal: ['$modal', function ($modal) {
return $modal;
}]
},
onEnter: ['$state', '$modal', function ($state, $modal) {
$modal
.open({
templateUrl: 'detail.html',
backdrop: 'static'
})
.result.then(function () {
$state.transitionTo('item.detail', {id: $state.params.id}, {reload: true});
})
;
}]
})
This refreshes the item and detail together.
Adding the state the to reload also doesn't work.
Any idea what I'm doing wrong?
Is this what you want to do, I think the interesting part if the reload argument (that you are using):
If reload is a string (or state object), the state object is fetched
(by name, or object reference); and \ the transition reloads the
resolves and views for that matched state, and all its children
states.
How do I get parameters for a state from a service?
I have this state:
.state('cashbox.list', {
title: 'Cashbox',
url: '/:from/:to?q',
templateUrl: '/cashbox_list.html',
controllerUrl: 'controllers/CashboxCtrl.js',
controller: 'CashboxCtrl',
controllerAs: 'mainCtrl',
params: {
from: getCashboxParamFrom,
to: getCashboxParamTo
},
resolve: {
cashboxData: getTransactionsData
}
})
function getTransactionsData($stateParams)
{
return CashboxService.getTransactions($stateParams.from, $stateParams.to);
}
Now my problem is, that params from and to are dynamic and are fetched by another service. I need something like a resolve before the resolve to get the params. I already tried to operate with promises in getCashboxParamTo/From but the app then stops routing when going to state. Also tried to use a parent state with redirectTo into child state but don't find anything on how to dynamically create stateparams from resolved data in parent state.
.state('cashbox', {
title: trns('title.cashbox_list'),
url: '/cashbox',
redirectTo: {
state: 'cashbox.list',
params: HERE DATES FROM RESOLVE
},
resolve: {
dates: getFromToDates
}
})
Solutions with state.go won't work as I'm running into a 'The transition has been superseded by a different transition' issue.
The answer is to declare two states cashbox and cashbox.list. Then redirect in a onStart transition hook after fetching data from service:
$transitions.onStart({to: 'cashbox'}, function (trans)
{
var curMonth = gfService.getCurrentMonth();
return $state.target('cashbox.list', {from: curMonth.dateFrom.string, to: curMonth.dateTo.string})
});
Let's say I've configured an state as follows:
{
name: "results",
parent: "modules/globalSearch/main",
url: ""
// other settings
}
* Note that I'm not using URLs. "modules/globalSearch/main" is the actual state name
In the other hand, "modules/globalSearch/main" is configured as follows:
$stateProvider.state({
name: "modules/globalSearch/main",
abstract: true
// other settings
});
Since "results" is a child of "modules/globalSearch/main", I would expect to call $state.go as follows:
$state.go("modules/globalSearch/main.results");
But UI Router will say that it can't transition to such state, and I can do so if I just call $state.go("results").
What's wrong here?
Try $state.go("modules.globalSearch.main.results");
EDIT :
By the way, I don't know how you declared your states in config.js
but that should stand this form:
.state('parent', {
url : '/parent',
templateUrl : 'url
})
.state('parent.child', {
url : '/child/:parameter/',
templateUrl : 'url
})
BR
I'm defining a page title in my state object as advised here.
$stateProvider
.state('project', {
url: '/projects/:origin/:owner/:name',
template: '<project></project>',
data : { pageTitle: 'Project page title'},
});
so i can access it this way later on:
$state.current.data.pageTitle
Now ... What i'd like to do is that instead of having a fixed value as pageTitle i'd like to access one the stateParams.
BEWARE, below exemple is not working, this is the way i'd like it to work.
$stateProvider
.state('project', {
url: '/projects/:origin/:owner/:name',
template: '<project></project>',
data : { pageTitle: $stateParams.name},
});
I could also use the attribute resolve :
resolve: { title: 'Project page title' },
For stateParams value i could do that:
resolve:{
pageTitle: ['$stateParams', function($stateParams){
return $stateParams.name;
}]
}
But then console.log($state.current.resolve.pageTitle); in my controller will return the entire function and not the result.
What would be the proper way to do that?
UPDATE :
The thing which i didn't mention is that i use angularJs with ES6 and i use a modular architecture.
Therefore each component has its own scope.
You can check my previous post to have a better idea about the modular architecture i'm using.
I'm building a breadcrumb grabbing the parent states (using the defined pageTitle).
Therefore defining the page title name in each module would be perfect.
So i can decide if the page title would be a fixed value "My page title" or a stateParams value.
Maybe this is totally wrong and this should not be done that way. Let me know if it is the case.
If you use a resolve like your example:
resolve:{
pageTitle: ['$stateParams', function($stateParams){
return $stateParams.name;
}]
}
You'll need to inject pageTitle into your controller:
angular.module('app').controller('controller', [
'pageTitle',
function (pageTitle) {
}
]);
But i don't see how that is any different from injecting $stateParams:
angular.module('app').controller('controller', [
'$stateParams',
function ($stateParams) {
}
]);
I'm trying to use $urlRouterProvider to redirect me from a parent state to a child one, though the child one is a URL that accepts a parameter. (child url: /:page?pageId).
I am simply hoping to enter the application by entering from www.example.com/home, where the $urlRouterProvider should then take over the routing.
The code looks something like this:
$urlRouterProvider.when('/home', '/home/?pageId=1');
$stateProvider.state('home', {
url: '/home',
abstract: true,
templateUrl: 'home.tpl.html'
}).state('home.page', {
url: '/:page?pageId',
templateUrl: '...'
});
As you can see, I was hoping that by using the $urlRouterProvider I would be able to direct the location from the /home (parent state) to the parameterized child state /:page?pageId by forcing the url /?pageId=1. Instead, it just appends a trailing slash to /home/.
Here is a very dysfunctional plnkr of this madness: http://plnkr.co/edit/XZ4jkhqzQmykIgx0CvH2?p=preview
Thanks!
There is a working plunker
I am not sure why the above notation is not working (if intended to skip it or not), but with this adjustment it will work:
$stateProvider.state('home', {
url: '/home',
abstract: true,
templateUrl: 'home.html',
controller: 'controller',
}).state('home.child', {
url: '/:page?pageId',
templateUrl: 'childtemplate.html',
params : { // HERE we do define the defaults
pageId: {value: 1}, // these would serve as a starting value
}
});
So, what we are effectively doing here, is to declaring the default value out of url, but in the params: {} setting:
...
params : {
pageId: {value: 1},
}
Check it here