I setup a small example based on the article posted on setting up UI routing.
I modified the example to test explicitly navigating from a child nested state to sibling state using $state.go(). any ideas what I am doing wrong?
I keep getting the error below:
Error resolving State. Could not resolve .paragraph from state home.list
$stateProvider
// HOME STATES AND NESTED VIEWS ========================================
.state('home', {
url: '/home',
templateUrl: 'partial-home.html'
})
// nested list with custom controller
.state('home.list', {
url: '/list',
templateUrl: 'partial-home-list.html',
controller: function($scope,$state) {
$scope.dogs = ['Bernese', 'Husky', 'Goldendoodle'];
$scope.navigateToNextState = function () {
$state.go('.paragraph');
};
}
})
// nested list with just some random string data
.state('home.paragraph', {
url: '/paragraph',
template: 'I could sure use a drink right now.'
})
http://plnkr.co/edit/Nae6xz9qcBp3IRYi0wcD?p=preview
Controller should be adjusted like this:
controller: function($scope, $state) {
$scope.dogs = ['Bernese', 'Husky', 'Goldendoodle'];
$scope.navigateToNextState = function () {
$state.go('^.paragraph');
};
}
We need a $state as one of function params. And we are in a child, so we have to use '^.paragraph' (instead of '.paragraph') to ask for another child of our parent
Checked working fixed version here
Related
I am using the angular UI state router using this example:
http://plnkr.co/edit/IzimSVsstarlFviAm7S7?p=preview. The router looks like this it has different urls for each state:
// HOME STATES AND NESTED VIEWS ========================================
.state('home', {
url: '/home',
templateUrl: 'partial-home.html'
})
// nested list with custom controller
.state('home.list', {
url: '/list',
templateUrl: 'partial-home-list.html',
controller: function($scope) {
$scope.dogs = ['Bernese', 'Husky', 'Goldendoodle'];
}
})
// nested list with just some random string data
.state('home.paragraph', {
url: '/paragraph',
template: 'I could sure use a drink right now.'
})
// ABOUT PAGE AND MULTIPLE NAMED VIEWS =================================
.state('about', {
url: '/about',
views: {
'': { templateUrl: 'partial-about.html' },
'columnOne#about': { template: 'Look I am a column!' },
'columnTwo#about': {
templateUrl: 'table-data.html',
controller: 'scotchController'
}
}
});
I would like to implement the UIrouter without changing the urls:at the moment the url changes when I change the state. Suppose I am trying to create a page where I have to add a parameter how can I pass on the parameter?
You can not do that. Only one way is custom implementation of routing. I made one time something like that. All containers for all subpages were fixed. Content was dynamically loaded using $http post. Changes were detected by listening of visible ID of container. A lot of stupid work. Most easier is to use ui - routing.
I am trying to put a nested view inside my modal. I can pull in the first-layer views fine but the nested view is tricking me somehow. Not sure what I am missing here?
http://plnkr.co/edit/g9cScdORPOz57zGCzQDA
var App = angular.module('App', ['ui.router']);
// routes
// -------------------------
App.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
// default state route
.state('app',{
url: '/',
views: {
'content': {
templateUrl: 'home.html'
},
'modals': {
templateUrl: 'modal.html'
}
}
})
// + modal content
.state('app.form', {
url: '/form',
views: {
'modal-content#modals': {
templateUrl: 'form.html'
}
}
})
//catch all route
$urlRouterProvider.otherwise('/');
})
Like Nikhil.agw said, you are not changing your state when you open your modal.
You could do it like that: http://plnkr.co/edit/eMNBBUYmKI6PRPiyU4xx?p=preview
<li>Open this modal</li>
Then just include a way to return to the previous state when the modal closes.
It is not going to work because on click you are only toggling the modal. Your state/route is not being changed. And route/state is not being changed, how will the nested state come in picture?
I am arriving on bookDetails state form some other link. Here bookDetails state's template has links for different tabs (or templates). And associated controller EditBookController has a json file using which I am building forms in different tabs with states like bookDetails.basic and bookDetails.publisher which use parent EditBookController. It's working fine. How to directly display the default bookDetails.basic instead of making user click the link? If I make bookDetails abstract(abbstract:true) and provide an empty link to bookDetails.basic I get following error Cannot transition to abstract state 'bookDetails'
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url:'/home',
controller: 'HomeController',
templateUrl: '/static/publisher/views/Publisher_Home_Template.html'
})
.state('books', {
url:'/books',
controller: 'BooksController',
templateUrl: '/static/publisher/views/Book_Listing_Template.html'
})
.state('bookDetails', {
url : '/books/:b_id',
controller: 'EditBookController',
templateUrl: '/static/publisher/views/Product_Page_Template.html'
})
.state('bookDetails.basic', {
url : '/basic',
templateUrl: '/static/publisher/views/tab1.html'
})
.state('bookDetails.publisher', {
url : '/publisher',
templateUrl: '/static/publisher/views/tab2.html'
})
A plunk with similar problem. but code is different On clicking form it should land on the profile profile form.
I created working example here
There is similar question: Redirect a state to default substate with UI-Router in AngularJS
The solution comes from a cool "comment" related to an issue with redirection using .when() (https://stackoverflow.com/a/27131114/1679310) and really cool solution for it (by Chris T, but the original post was by yahyaKacem)
https://github.com/angular-ui/ui-router/issues/1584#issuecomment-75137373
In the state definition I added ONLY one setting to bookDetails state, the: redirectTo: 'bookDetails.basic',. Let's have a look:
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url:'/home',
controller: 'HomeController',
templateUrl: '/static/publisher/views/Publisher_Home_Template.html'
})
.state('books', {
url:'/books',
controller: 'BooksController',
templateUrl: '/static/publisher/views/Book_Listing_Template.html'
})
.state('bookDetails', {
// NEW LINE
redirectTo: 'bookDetails.basic',
url : '/books/:b_id',
controller: 'EditBookController',
templateUrl: 'static/publisher/views/Product_Page_Template.html'
})
.state('bookDetails.basic', {
url : '/basic',
templateUrl: '/static/publisher/views/tab1.html'
})
.state('bookDetails.publisher', {
url : '/publisher',
templateUrl: '/static/publisher/views/tab2.html'
})
And now - only these few lines will do the miracle:
app.run(['$rootScope', '$state',
function($rootScope, $state) {
$rootScope.$on('$stateChangeStart',
function(evt, to, params) {
if (to.redirectTo) {
evt.preventDefault();
$state.go(to.redirectTo, params)
}
}
);
}]);
This way we can adjust any of our states with its default redirection...Check it here
From Directing the user to a child state when they are transitioning to its parent state using UI-Router:
Either change the bookDetails.basic state to:
.state('bookDetails.basic', {
url : '',
templateUrl: '/static/publisher/views/tab1.html'
})
Or add the following routing:
$urlRouterProvider.when('/books/{b_id}', '/books/{b_id}/basic');
Try to add $state.go('bookDetails.basic') inside EditBookController. If I understood you< this will help.
Question: For some reason I can't get my controller to recognize my url parameters across sessions.
Background: I have a nested view called modal that takes a parameter, whose url is /modal/:id (eg: /#/modal/1/ or /#/floorplan/1+2/). Ideally, when the user goes to this url, a modal will automatically open with the resource(s) with the given id.
Since the parent state and the child state(modal) are being handled by the same controller, the modal state has a custom data attribute (modalStatus) in its configuration set to true. When this custom attribute is enabled the modal is displayed.
I can currently go from the parent state to the nested state and trigger the modal but when I start a new session or refresh the page with a url like /modal/3, the application fails to read the parameters ($stateParams), which is being logged as an empty object.
I have tried using onEnter and Resolve but I'm not exactly clear on how to use them in this scenario.
Router
$stateProvider
.state('home', {
name: 'home',
url: '/',
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.state('home.modal', {
url: 'modal/:id/',
data: {
modalState: true
},
controller: 'MainCtrl'
})
Relevant part of controller:
$scope.init = function() {
console.log($stateParams);
if ($state.current.data) {
if ($state.current.data.modalState === true) {
$scope.openModal();
}
}
};
$scope.init();
edit: plunkr
You could try adding the params option:
$stateProvider
.state('home', {
name: 'home',
params: {
id: null
},
url: '/',
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.state('home.modal', {
url: 'modal/:id/',
data: {
modalState: true
},
controller: 'MainCtrl'
});
The child state home.modal should inherit the params of the parent. On your ui-sref from one state to another, pass the param like so:
<a ui-sref="home.modal({ id: x })"></a>
Then your url would turn out to be /modal/:x (where x is the number).
Also the $stateParams should then show the params as you wished.
i can't get this structure to work!
I am trying to resolve my sidebarActions when the parent root state is called so the value can be used in all root.child states.
When i use root as a parent i don't get a view, tried to read about ui.router but i cant figure out what i am doing wrong. There is a ui-view="" specified in my layout & i can display home state if i remove root.
I also want to ask if i am planing this right? My goal is to fill out data for the sidebar based on state and IF the state has a sidebar view.
app.config([
'$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
// For any unmatched url, redirect to root
$urlRouterProvider.otherwise('/');
$stateProvider
.state('root', {
url: '',
'abstract': true,
resolve: {
// Will resolve som data here for the child views.
sideBarActions: function () {
return { value: 'simple!' };
}
}
})
.state('root.home', {
url: '/',
templateUrl: '/App/Main/views/home/home.cshtml',
controller: 'app.controllers.views.home', // sideBarActions is injected in controller
});
}
]);
EDIT CREATED A PLUNKR:
Plunkr
This is how far i am, i have created the routes so they work. But i still want to solve the problem where im not doing this DRY.
Can i create this without repeating the sidebar all the time? and inject the resolved data inside the controller if the view should have a sidebar?
I did updated your plunker a bit here. Firstly the left and main areas are moved into root state - which is still abstract.
There are two substates home and customers... for which also generated navigation on the left, basd on the rosolved sideBarActions. Finally, there is a customer detail, substate of customers.
$stateProvider
.state('root', {
url: '',
'abstract': true,
resolve: {
sideBarActions: function() {
return {
actionNames: ['root.home','root.customers']
};
}
},
views: {
'': { templateUrl: 'tpl.layout.html',},
'sidebar#root': {
templateUrl: 'tpl.actionBar.html',
controller: 'actionBarCtrl',
}
}
})
.state('root.home', {
url: '/',
template: '<div>root.home content</div>',
})
.state('root.customers', {
url: '/customers',
templateUrl: 'tpl.customers.html',
})
.state('root.customers.customer', {
url: '/:customerId',
template: '<div>customer with {{id}}</div>',
controller: function($scope, $stateParams)
{$scope.id = $stateParams.customerId},
})
The only place where we can see absolute naming is in the root state definition, where we introduce the template, and do inject into there as well 'sidebar#root': {...}
That all should show how the ui-router multi-views and nested-states could bring us lot of profit. Check it here