I have those 2 states for my page :
$stateProvider
.state("page", {
url: "/:pageId/:pageType",
template: pageTemplate,
controller: "contentCtrl",
resolve: {
...
}
},
params: {reload: true}
})
and
.state("schedule", {
url: "/Schedule/:scheduleId/:pageId/:pageType",
template: pageTemplate,
controller: "contentCtrl",
resolve: {
...
}
},
params: {
pageId: { squash: true, value: null},
pageType: { squash: true, value: null},
reload:true
}
})
SOMETIMES, for link's like this :
http://localhost:8182/index.html#/Schedule/691d6981b8dd47e0a158d67cb02b1fee/
the 'page' state is loading instead of the 'schedule' one.
What should I do to fix this?
PS: I'm using AngularJS v1.7.6 and ui-router v0.2.18
The routes are matched in the order they are defined. However, exact matches take precedence over parameterized matches.
I would at first try to change the order of the states.
then I would try to do something like
$stateProvider.state('foo.bar', {url: '/foo/:bar'});
$stateProvider.state('foo.baz', {url: '/foo/baz'});
$urlRouterProvider.when( '/foo/baz', function($state){ $state.go('foo.baz'); } );
Also I see two problems:
what's with that uppercase in /Schedule/
what's with params: {reload: true}"
Related
I am trying to pass data from one controller to another using $stateParams but getting null instead of valid data:
Please find my route code below:
.state("root.home", {
url: "/home",
abstract: true,
template: homeHtml,
controller: "HomeCtrl as ctrl",
})
.state("root.home.content", {
url: "",
params: {
userId: null,
},
views: homeView,
})
Controller A code:
$state.go("root.home.content", {userId}); // getting correct UserId
HomeCtrl code:
// In its constructure I injected the $stateParams
init() {
console.log($stateParams); // getting undefined here
if ($stateParams && $stateParams.userId) {
this.loadUser($stateParams.userId);
}
}
Pass your parameter as below
$state.go("root.home.content", {'userId': userId});
//This userId should be a valid variable inside your Controller A
And also you should edit your router as below,
.state("root.home.content", {
url: "/:userId",
params: {
userId: null,
},
views: homeView,
})
Otherwise it will not show in the url & cannot access from $stateParams
I fixed this by adding params to parent root instead of child. The correct code is:
.state("root.home", {
url: "/home",
params: {
userId: null,
},
abstract: true,
template: homeHtml,
controller: "HomeCtrl as ctrl",
})
.state("root.home.content", {
url: "",
views: homeView,
})
So i have 2 routes set up:
$stateProvider.state('accounts', {
abstract: 'true',
url: "/accounts",
template: '<div ui-view></div>'
}).state('accounts.view', {
url: "/:accountNumber",
views: {
'#': {
templateUrl: 'tpl/account/index.html',
controller: 'AccountController',
controllerAs: 'controller'
}
},
resolve: {
today: ['today', function (today) {
// Return todays date
return today();
}],
tomorrow: ['tomorrow', function (tomorrow) {
// Return tomorrows date
return tomorrow();
}],
lastMonth: ['lastMonth', function (lastMonth) {
// Return lastMonths date
return lastMonth();
}],
account: ['$stateParams', 'AccountService', function ($stateParams, accountService) {
console.log('hi');
return accountService.get($stateParams.accountNumber);
}]
},
data: {
requireLogin: true,
pageTitle: 'Account details'
}
}).state('accounts.create', {
url: '/create',
views: {
'#': {
templateUrl: 'tpl/account/save.html',
controller: 'AccountSaveController',
controllerAs: 'controller'
}
},
resolve: {
account: function () {
return {};
}
},
data: {
requireLogin: true,
pageTitle: 'Create account'
}
}).state('accounts.view.edit', {
url: '/edit',
views: {
'#': {
templateUrl: 'tpl/account/save.html',
controller: 'AccountSaveController',
controllerAs: 'controller'
}
},
data: {
requireLogin: true,
pageTitle: 'Edit account'
}
})
If I click a button decorated with ui-sref='accounts.create' it will navigate to the correct view, but it tries to do the resolve in accounts.view. It seems that the :accountNumber is being confused with /create.
If I refresh my page, it doesn't load the view and still tries to resolve the account.
I have tried a number of ways to solve this.
I would like to have the urls like this:
accounts/:accountNumber - for viewing an account
accounts/create - for creating an account and
accounts/:accountNumber/edit - For editing an account
Is it possible to set up the routes like that?
If your accountNumber is a number indeed, you can define your account.view state as url: "/{accountNumber:int}". That will prevent accounts/create from matching it. Otherwise, you can use some custom regex see docs to achieve the same.
You may also find GitHub issue useful.
I have a state definition like this:
$stateProvider.state('password', {
url: '/password',
templateUrl: 'password.html',
controller: 'PasswordController',
controllerAs: 'ctrl',
params: {
accountNumber: {
value: null,
squash: true
}
},
});
I need to reference this state with its href rather than using ui-serif directive, How can I set params.accountNumber inside href?
This doesn't work:
$state.href('password', {accountNumber: $scope.accountNumber})
When I change this line url: '/password', to ` url: '/password?accoutNumber', and remove this part
params: {
accountNumber: {
value: null,
squash: true
}
},
$state.href works just fine.
To be able to generate URL with $state.href and pass parameter...
such parameter must be part of url definition
declaring it just in params: {} will result in href - not containing it, not passing it
there is adjusted state definition:
.state('password', {
url: '/password/:accountNumber',
templateUrl: 'password.html',
controller: 'PasswordController',
controllerAs: 'ctrl',
params: {
accountNumber: {
value: null,
squash: true
},
},
});
There is a working plunker
ORIGINAL part, related to typo
The $state.href() call seems to be ok... just a state definition could be wrong:
$stateProvider.state('password', {
//Url: '/password',
url: '/password',
...
The url setting is case sensitive. See state.href doc here:
href(stateOrName, params, options)
I have multi pages with One View .I want use Single View for All pages, with Logical structure Angular, In addition Breadcrumbs for navigation, in head of Home page.
config code:
$stateProvider
.state('otherwise', {
url: '*path',
controller: function ($state) {
var lastUrl = sessionStorage.lastUrl
if (lastUrl && lastUrl != 'otherwise')
$state.go(lastUrl);
else if (!lastUrl)
$state.go('Companies');
},
data: {
requireLogin: false
}
})
.state('Create', {
controller: 'myControl',
url: '/',
templateUrl: 'Create.html',
data: {
requireLogin: true
}
})
.state('Jobs', {
controller: 'myControl',
url: '/',
templateUrl: 'JobsList.html',
data: {
requireLogin: true
}
})
.state('Companies', {
controller: 'myControl',
url: '',
templateUrl: 'CompaniesList.html',
data: {
requireLogin: false,
breadcrumbProxy: 'Companies.CarsList'
}
})
.state('Companies.CarsList', {
controller: 'myControl',
params: { id: ':id', companyName: ':companyName' },
url: '',
templateUrl: 'CarsList.html',
data: {
requireLogin: false,
displayName: 'List'
}
})
.state('Companies.CarsInfo', {
controller: 'myControl',
templateUrl: "CarInfo.html",
data: {
requireLogin: false,
displayName: 'Info'
}
})
html:using single VIEW in home page
<div ui-view></div>
You have a Solution for my Config?!
Single view
To handle multiple views, the ui-router provides rules to target views when you have multiple <div ui-view></div> in your templates.
By default, a state takes place in the unique <div ui-view></div> in parent state. So, given your configuration, the Companies.CarsList template will be inserted in the <div ui-view></div> of the Companies state (in CompaniesList.html).
To override that, just wrap templateUrl and controller of your second-level states (Companies.CarsList and Companies.CarsInfo) in a views object the ui-router to place the view in the unique <div ui-view></div> of the root state (in index.html), like this:
.state('Companies.CarsList', {
params: { id: ':id', companyName: ':companyName' },
url: '',
views: {
"#": { // rule for absolutely targetting the unnamed view in root unnamed state.
controller: 'myControl',
templateUrl: 'CarsList.html',
}
},
data: {
requireLogin: false,
displayName: 'List'
}
})
Breadcrumb
Have a look on angular-breadcrumb, it generates a breadcrumb based on the ui-router configuration. All you have to do is to give a name to the states (like you seems to do already with data > displayName).
The module can handle the absolute view targeting I described above. See the docs for details
I have a $state configured as below:
.state('app.subjects.current', {
abstract: true,
url: "/:subjectId",
template: "<div ui-view />",
ncyBreadcrumb: {
skip: true
}
})
.state('app.subjects.current.home', {
url: '/home',
templateUrl: "assets/src/subject/subjectHome.html",
resolve: loadSequence('subjectHomeCtrl'),
ncyBreadcrumb: {
label: 'View'
},
string: 'sidebar.nav.pages.SUBJECTHOME'
})
I transit to this state using $state.go('app.subjects.current.home', {subjectId: '999'});
The url appears in the address bar as “http://localhost:12253/#/app/subjects//home?subjectId=999”. It should have been actually “http://localhost:12253/#/app/subjects/999/home”.
Thanks for any help.
I created working example with exactly the same mapping - to show you that your approach is working
So, these are the states
.state('app', {
template: '<div ui-view=""></div>',
})
.state('app.subjects', {
template: '<div ui-view=""></div>',
})
.state('app.subjects.current', {
abstract: true,
url: "/:subjectId",
template: "<div ui-view />",
ncyBreadcrumb: {
skip: true
}
})
.state('app.subjects.current.home', {
url: '/home',
templateUrl: "assets/src/subject/subjectHome.html",
//resolve: loadSequence('subjectHomeCtrl'),
ncyBreadcrumb: {
label: 'View'
},
string: 'sidebar.nav.pages.SUBJECTHOME'
})
And this way we can call them
// $state.go
<button ng-click="$state.go('app.subjects.current.home', {subjectId: '999'});">
// ui-sref
<a ui-sref="app.subjects.current.home({subjectId: '888'})">
Check it here. It should help to find out what is different in your app...