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.
Related
In this sample what I need is that in plnkr.co/edit/5FVrydtTPWqYMhhLj03e?p=preview, when I click the Contact Numbers button, It will redirect to the Contact Numbers page in the Contacts.
Im using Angular JS and I hope someone can help me.
scotchApp.config(function($routeProvider) {
$routeProvider
// route for the home page
.when('/', {
templateUrl : 'pages/home.html',
controller : 'mainController'
})
// route for the about page
.when('/about', {
templateUrl : 'pages/about.html',
controller : 'aboutController'
})
// route for the contact page
.when('/contact', {
templateUrl : 'pages/contact.html',
controller : 'contactController'
});
});
Credits to https://scotch.io/tutorials/angular-routing-using-ui-router for I am forking their example
Your code shows a ng-route example but the link you provide is a ui-router example. ($routeProvider vs $stateProvider).
If you would be using the $stateProvider from angular-ui-router to define the states you'll be using throughout your application it would probabably be more like the following:
$stateProvider.state('home', {
controller: 'mainController',
url: '/',
templateUrl: 'pages/home.html'
});
$stateProvider.state('about', {
controller: 'aboutController',
url: '/about',
templateUrl: 'pages/about.html'
});
$stateProvider.state('contact', {
controller: 'contactController',
url: '/contact',
templateUrl: 'pages/contact.html'
});
You see that a definition of a state uses a string to identify itself with: e.g. :'home', 'contact' etc. You can use the $state service from ui-router and use the \[go(to, params, options)\] method to transition between states in combination with this identifier.
Convenience method for transitioning to a new state. $state.go calls
$state.transitionTo internally but automatically sets options to {
location: true, inherit: true, relative: $state.$current, notify: true
}. This allows you to easily use an absolute or relative to path and
specify only the parameters you'd like to update (while letting
unspecified parameters inherit from the currently active ancestor
states).
All you need to do is to couple this to the click event of you button in your maincontroller. That is: inject $state into your mainController and couple an ng-click within your button to a function that executes $state.go().
<button type="submit" ng-click="$state.go('contact')">Contact Numbers</button>
Here is the plunker link for the code http://plnkr.co/edit/JwM8t3oNepP3tE1nUXlM?p=info
controller.js
if(($scope.login==='Admin')&&($scope.password==='admin'))
{
$state.go('login.home');
}
script.js
var DailyUsageApp = angular.module('DailyUsageApp', ['ui.router']);
DailyUsageApp.config(function($stateProvider, $locationProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/login');
$stateProvider.state('login', {
url: '/login',
templateUrl: "login.html",
controller: 'authController'
})
.state('login.home', {
url: '/home',
templateUrl: "home.html",
controller: 'homeController'
});
});
The reason your code isn't working is because you are creating hierarchical states, that are not meant to be hierarchical. By naming your state login.home, you are saying that home is a child of login. This means that when you try and go('login.home') ui router is attempting to render the login state as well as the home state as a child. This means that for your current layout to work, the login template must contain its own ui-view tag. The best way to fix this is to simply rename your state to just home, and then use $state.go('home');
There is an updated plunker
The most simple solution is to NOT make state login.home nested under login.
//.state('login.home', {
.state('home', {
url: '/home',
templateUrl: "home.html",
controller: 'homeController'
});
There are also other solutions, like create a target for login.home inside of the login like this:
<div ui-view=""></div
But usually, we do not do that. Just login and then navigate to some other state hierarchy...
I am writing an AngularJS Application using ui-router. The states 'home' and 'book' are loaded into the (parent) - ui-view element
My setup for the routes is as following :
.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/home2/app'
})
.state('book', {
url: '/book',
templateUrl: '/book/index'
})
.state('book.overview', {
url: '/overview',
templateUrl: '/book/overview'
})
.state('book.edit', {
url: '/edit/:bookid',
templateUrl: '/book/detail',
controller: 'bookeditcontroller'
})
.state('book.create', {
url: '/create',
templateUrl: '/book/detail',
controller: 'bookeditcontroller'
});
});
When the user tiggers the 'book' state (through a href), the template from '/book/index' is loaded and displayed successfully. But on this first request, i also want to load the template from '/book/overview' and displaying it in the child ui-view.
i've already read the topics about the default states under https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-set-up-a-defaultindex-child-state
But this is not exactly the behavior i want. Is there a way to tell ui-router when parent state 'book' is loaded, also load 'book.overview' into its (child) ui-view ?
Thanks for you help!
I would say that you will need
Multiple Named Views
This allows us to think in one state - many views
State would look like this
.state('book', {
url: '/book',
views : {
'' : { templateUrl: '/book/index', },
'#book': {templateUrl: '/book/overview' },
}
})
this way, we will place two views into one state.
The first will be injected into index.html/root <div ui-view=""></div>
The second will be placed inside of the templateUrl: '/book/index',
That's how we can play with many views in one (or even more parent, grand parent...) state.
I created a plunker with layout, which does show a bit similar example. The code snippet of the state with many views is:
$stateProvider
.state('index', {
url: '/',
views: {
'#' : {
templateUrl: 'layout.html',
controller: 'IndexCtrl'
},
'top#index' : { templateUrl: 'tpl.top.html',},
'left#index' : { templateUrl: 'tpl.left.html',},
'main#index' : { templateUrl: 'tpl.main.html',},
},
})
I have the following states:
$stateProvider.
state('candidates', {
abstract: true,
url: '/candidates',
templateUrl: '/Scripts/App/js/Views/candidates/candidates.html',
controller: 'candidatesTableController'
}).
state('candidates.item', {
url: '/{item:[0-9]{1,4}}',
templateUrl: '/Scripts/App/js/Views/candidates/candidate.html',
controller: 'candidatesDetailController'
}).
state('candidates.item.details', {
url: '/details',
templateUrl: '/Scripts/App/js/Views/candidates/partials/generalDetails.html',
controller: function($scope, $stateParams) {
$scope.item= $stateParams.item;
}
}).
state('candidates.item.edit', {
url: '/details/edit',
templateUrl: '/Scripts/App/js/Views/candidates/partials/form.html',
controller: function($scope, $stateParams) {
$scope.item = $stateParams.item;
}
}).state('candidates.item.photo', {
url: '/details/photo',
templateUrl: '/Scripts/App/js/Views/candidates/partials/updatePhotoID.html',
controller: function($scope, $stateParams) {
$scope.item = $stateParams.item;
}
});
Here my urlRouterProvider:
$urlRouterProvider
.when('/candidates/:item', '/candidates/:item/details')
.otherwise("/");
When I use ui-sref everything work fine but when i using the actual url, it never can find the following url:
"/#/candidates/4/details"
it redirect to the root ("/#/")
I can't figure out why?
Thanks
I created a plunkr with your routes defined here:
http://run.plnkr.co/Sn3s7ooM6MOSxQnB/#/candidates/4/details
Code visible here:
http://plnkr.co/edit/wArFenIZ7j3WczUhtJO6
Notice that the first link in this answer takes you right to the details page for a candidate item. Maybe you can figure out from my simplified code what it is that you need to change to achieve the same behavior.
Also, I noticed that your redirect doesn't work (the second nav item in my plunker allows you to go to this state without a redirect; try clicking it yourself):
.when('/candidates/:item', '/candidates/:item/details')
This redirect will work if you set the candidates.item state to be abstract. Maybe this is what you want.
See this in action here: http://plnkr.co/edit/y9LI0OKGMStVnMY2NX5q
Code visible here: http://plnkr.co/edit/y9LI0OKGMStVnMY2NX5q
I hope that helps
Right now i am using routeProvider to change between views which works awesome. But now i want to create a view which contains 4 different tabs which should contain 4 different controllers. ive read here that it could be done with stateProvider:
Angular ui tab with seperate controllers for each tab
here is my code:
var WorkerApp = angular.module("WorkerApp", ["ngRoute", 'ngCookies', "ui.bootstrap", "ngGrid", 'ngAnimate', 'ui.router']).config(function ($routeProvider, $stateProvider) {
$routeProvider.
when('/login', {
templateUrl: 'Home/Template/login', resolve: LoginCtrl.resolve
})
.when('/register', { templateUrl: 'Home/Template/register', resolve: RegisterCtrl.resolve })
.when('/', { templateUrl: 'Home/Template/main', resolve: MainCtrl.resolve })
.when('/profile', { templateUrl: 'Home/Template/profile', controller: "ProfileController" })
.when('/contact', { templateUrl: 'Home/Template/contact', controller: "ContactController" })
$stateProvider.state('tabs', {
abstract: true,
url: '/profile',
views: {
"tabs": {
controller: "ProfileController",
templateUrl: 'Home/Template/profile'
}
}
}).state('tabs.tab1', {
url: '/profile', //make this the default tab
views: {
"tabContent": {
controller: "ProfileController",
templateUrl: 'Home/Template/profile'
}
}
})
.state('tabs.tab2', {
url: '/tab2',
views: {
"tabContent": {
controller: 'Tab2Ctrl',
templateUrl: 'tab2.html'
}
}
});
});
but i cant get it really to work because default of routeprovider is set to send over to work because my routeprovider is sending over to "/" on default, which makes "/tabs" invalid. so i cant actully figure out if it is possible to switch to states on specific url. Or change state on specific URL in routeProvider?
I can't tell you for sure exactly what's wrong with the code you've provided, but I'm using Angular UI-Router with the same use case you described, and it's working for me. Here's how I have it configured and how it's different from your configuration:
I don't use $routeProvider at all (none of your $routeProvider.when statements). I'm pretty sure you should not be using $routeProvider since you're using $stateProvider.
I have one use of the $urlRouterProvider with an 'otherwise' statement to specify a default URL:
$urlRouterProvider.otherwise("/home");
My calls to $stateProvider.state is a little different from yours. Here's the one for the parent view of the tabs:
$stateProvider.state('configure', {
url: "/configure",
templateUrl: 'app/configure/configure.tpl.html',
controller: 'ConfigureCtrl'
});
Here's an example of the child state (really the same except for the state name being parent.child format, which you already have in your code; and I added a resolve block but you could have that on the parent as well):
$stateProvider.state('configure.student', {
url: "/student",
templateUrl: 'app/configure/student/configure.student.tpl.html',
controller: 'ConfigureStudentCtrl',
resolve: {
storedClassCode: function($q, user, configureService) {
return configureService.loadMyPromise($q, user);
}
}
});
Also, I'm using version 0.2.8 of Angular UI-Router with version 1.2.9 of Angular. I think this would work with any version of Angular 1.2.0 or later.