Consider this code:
bank.config(function($stateProvider) {
$stateProvider
.state('main.bank', {
url: '/',
controller: 'BankCtrl',
resolve: {
money: function(bankResource) {
return bankResource.getMoney();
},
templateUrl: 'bank/bank.html'
});
});
Above I render the bank.html template once resolve is finished executing.
I want to render a specific template depending on what is returned from my money function.
Example:
if money returns an object with items, render bank.html
if money returns an empty object, then return empty-bank.html
How can I achieve this within my $stateProvider? Or would it even make more sense for it to be in a directive?
Move your resolve code to parent controller, create two child routes one for each of bank.html and empty-bank.html and route based on the result of resolve, something like this -
.state('main', {
url: '/',
controller: 'MainCtrl',
resolve: {
money: function(bankResource) {
return bankResource.getMoney();
}
})
.state('main.bank', {
url: '/blank',
controller: 'BankCtrl',
templateUrl: 'bank/bank.html'
})
.state('main.emptybank', {
url: '/emptyblank',
controller: 'EmptyBankCtrl',
templateUrl: 'bank/empty-bank.html'
});
Inject the result of resolve into your controller and change state based on the output.
In the index.html of your main state, switch views based on the money variable. E.a.:
.state('main', {
url: '/',
controller: 'MainCtrl'
})
In your MainCtrl set a variable based on the output of your function:
$scope.money = "bank"
or
$scope.money = "emptybank"
Then in your index.html call a view:
<div ng-view="{{$scope.money}}"></div>
In your router:
.state('main.bank', {
url: '/bank',
views: {
bank: {
controller: 'BankCtrl',
templateUrl: 'bank/bank.html'
},
emptybank: {
controller: 'EmptyBankCtrl',
templateUrl: 'bank/emptybank.html'
}
}
})
Sorry in advance for any syntax errors. Typed it from head on my mobile phone.
But this should fix your problem and in the progress make it more "Angularesque" :-)
Related
My question is simple, but I couldn't find solution anywhere else.
For example I have a normal route state with parameter,
.state('page', {
url: '/page/:pageid',
templateUrl: 'templates/pages.html',
controller: 'pagesCtrl'
})
However for example, if I have 1000 pages, but for the Number 1 and Number 999 pages I have to use another template. How could I simply do this? Something like
.state('page', {
url: '/page/:pageid',
templateUrl: 'templates/pages.html',
controller: 'pagesCtrl'
})
.state('page', {
url: '/page/1',
templateUrl: 'templates/page1.html',
controller: 'pagesCtrl'
})
.state('page', {
url: '/page/999',
templateUrl: 'templates/page999.html',
controller: 'pagesCtrl'
})
Will this work?I tested, the later 2 options are not overriding the original state with parameter.
If I wish to use the same controller, how to load the 1 and the 999 as the pageid parameter in the controller?
Definitely you shouldn't have two more state for separate template. You should use single generic state which will take templateUrl with the help of passed state parameter.
Code
.state('page', {
url: '/page/:id',
templateUrl: function($stateParams){
var template = $stateParams.id.indexOf([1, 1000]) > -1?'pages.html'
:'page'+$stateParams.id+'.html';
return 'templates/'+template ,
}
controller: 'pagesCtrl'
})
I have angular's ui-routing.
For example I have movies controller and there I have categories method and when user enter to /movies/categories I want to call this method
.state('movies', {
url: '/movies',
views: {
'pageContent': {
controller: 'movies',
templateUrl: 'movies.html'
}
}
})
How can I achieve something like this:
.state('moviesCategories', {
url: '/movies/categories',
views: {
'pageContent': {
controller: 'movies',
**method: 'categories',**
templateUrl: 'categories.html'
}
}
})
If you want to execute method on route change you can insert this code into categories.html
<div data-ng-init="categories();"> ... </div>
Better create separate controllers for each route. let's say 'categoriesController'.
$routeProvider
.when('/movie',{
templeteUrl:'templates/movies',
controller:'moviesController'
)
.when('/movies/categories',{
templeteUrl:'templates/movieCategories',
controller:'movieCategoryController',
resolve:{
categories://pull categories using a service here. inside service write $http call.
}
);
inside controller
//will inject the categories we got in reolve
angular.controller('movieCategoryController',['categories','$scope',functions(categories,$scope){
$scope.categories=categories;
}]);
in movies controler should add $state.go('moviesCategories'); this method redirect to state moviesCategories
samples in documentation
.state('state1', {
url: "/state1",
templateUrl: "partials/state1.html"
})
.state('state1.list', {
url: "/list",
templateUrl: "partials/state1.list.html",
controller: function($scope) {
$scope.items = ["A", "List", "Of", "Items"];
}
})
What I am trying to do is within the Search controller, once I get the search results back from the server ($http) change view to a different view - the search results view. I am not sure if the approach I am going about it is right, but either-way it doesn't seem to be working. I will need to pass the response as well, so the new view can display the results/response.
My app.js:
.....state('tab.search', {
url: '/search',
views: {
'tab-search': {
templateUrl: 'templates/tab-search.html',
controller: 'SearchCtrl as search'
}
}
})
.state('tab.search-results', {
url: '/results',
views: {
'tab-search-results': {
templateUrl: 'templates/tab-search-results.html',
controller: 'SearchResultsCtrl as searchResults'
}
}
})
Then my search controller has:
.controller('SearchCtrl', function($scope, $state, $location, $ionicPopup, service) {
....
$scope.doSearch = function(state) {
.....
var result = service.doSearch(dataObj);
result.then(function(response) {
console.log("I'm here");
$state.go('tab.search-results');
......
My search results view (tab-search-results.html) has the following basic code at the moment:
<ion-view view-title="Search Results">
<ion-content padding="true">
hello world
</ion-content>
</ion-view>
This basic structure is how all my other pages/views are setup too.
What happens when I perform the search is that the console message gets outputted, and then the URL changes to /results as per the tab.search-results state, but the template/view doesn't change/show.
Interestingly if I change $state.go('tab.search-results'); to point to another app state/view that I know works, it works perfectly - but for whatever reason this state/view isn't working.
Also, if there is a better way of achieving this same thing, then please let me know. I will be needing to eventually pass the "response" from SearchCtrl to SearchResultsCtrl - or rather access it on the search results page in one form or another.
Many thanks.
I think you are looking for $stateParams.
var result = service.doSearch(dataObj);
result.then(function(response) {
$state.go('tab.search-results', {'searchData':response});
}
In your routes file:
.state('tab.search-results', {
url: '/results/:searchData',
views: {
'tab-search-results': {
templateUrl: 'templates/tab-search-results.html',
controller: 'SearchResultsCtrl as searchResults'
}
}
})
And in your SearchResultsCtrl:
.controller($stateParams) {
console.log($stateParams.searchData) // will give you search results
}
NOTE:If you don't want to pass data through the URL you can use params key in the .state() method.
.state('tab.search-results', {
url: '/results',
params: {
'searchData':null
},
views: {
'tab-search-results': {
templateUrl: 'templates/tab-search-results.html',
controller: 'SearchResultsCtrl as searchResults'
}
}
})
I realised why my view wasn't changing properly. The fix was changing the views in the sub-view to reference the parent view.
Fail (sub-view has unique name from parent):
.....state('tab.search', {
url: '/search',
views: {
'tab-search': {
templateUrl: 'templates/tab-search.html',
controller: 'SearchCtrl as search'
}
}
})
.state('tab.search-results', {
url: '/results',
views: {
'tab-search-results': {
templateUrl: 'templates/tab-search-results.html',
controller: 'SearchResultsCtrl as searchResults'
}
}
})
Success (sub-view references parent, 'tab-search'):
.....state('tab.search', {
url: '/search',
views: {
'tab-search': {
templateUrl: 'templates/tab-search.html',
controller: 'SearchCtrl as search'
}
}
})
.state('tab.search-results', {
url: '/results',
views: {
'tab-search': {
templateUrl: 'templates/tab-search-results.html',
controller: 'SearchResultsCtrl as searchResults'
}
}
})
Thanks all, I think I worked out the problem. It was putting the search results page under the tab abstract state. eg: tab.search-results rather than search-results - I am guessing this was the problem as there is no search results tab. When I re-named the state to just search-results (and modified the $state.go to use 'search-results' instead of 'tab.search-results') it worked. Does this seem right?
I have a page showing the list of applications that I want to be able to go to the page of the details of the app, when I click on each one of them.
Here is my config:
module bandar {
'use strict';
export class RouterConfig {
/** #ngInject */
constructor($stateProvider: ng.ui.IStateProvider,
$urlRouterProvider: ng.ui.IUrlRouterProvider,
$locationProvider: ng.ILocationProvider) {
$stateProvider
.state('home', {
url: '',
abstract: true,
templateUrl: 'app/components/main/main.html',
controller: 'MainController',
controllerAs: 'mainCtrl'
})
.state('home.apps', {
url: '/apps',
abstract: true,
templateUrl: 'app/components/apps/apps.html',
controller: 'AppsController',
controllerAs: 'appsCtrl',
})
.state('home.apps.list', {
url: '',
templateUrl: 'app/components/apps/list.html',
})
.state('home.app.detail', {
url: '/app/:package_name',
templateUrl: 'app/components/apps/app.html',
controller: 'AppController',
controllerAs: 'appCtrl',
});
$urlRouterProvider.otherwise('/apps');
/*$locationProvider.html5Mode(true).hashPrefix('');*/
}
}
}
And here is the part of the list template which is anchoring to the app's details page:
<a ui-sref="home.app.detail({package_name: app.package_name})">{{app.title}}</a>
But when I hit it in my browser, the following error occurs in the console:
Error: Could not resolve 'home.app.detail' from state 'home.apps.list'
at Object.transitionTo (angular-ui-router.js:3140)
at Object.go (angular-ui-router.js:3068)
at angular-ui-router.js:4181
at angular.js:17682
at completeOutstandingRequest (angular.js:5387)
at angular.js:5659
I guess the problem is UI-Router thinks that I'm pointing at the state relatively, but I wanna do it in the absolute way.
The problem is parent name 'home.app' instead of 'home.apps'
// wrong
.state('home.app.detail', { ...
// should be
.state('home.apps.detail', { ...
because parent is
.state('home.apps', { ...
EXTEND in case, that this should not be child of 'home.apps' we have to options
1) do not inherit at all
.state('detail', { ...
2) introduce the parent(s) which is(are) used in the dot-state-name-notation
// exists already
.state('home', { ...
// this parent must be declared to be used later
.state('home.app', {
// now we can use parent 'home.app' because it exists
.state('home.app.detail', {
I want to give 2 parts of my UI the same controller but still let them have each of their own unique controllers.
$stateProvider
.state('standard.page', {
url: '/:page',
resolve: {
page: function($stateParams) {
...
},
},
views: {
'content': {
templateUrl: '/tmpl/page',
controller: 'controllercontent'
},
'sideMenu': {
templateUrl: '/tmpl/menu',
controller: 'controllermenu',
}
}
})
So I want both content and sideMenu to share a controller. If I add a controller above the views then it requires a new template, I want to use the standard template instead of making a unique template for this state. Any ideas how I can get 3 controllers going in this example? Thanks.
I battled with this at some point in time, and I believe I made a template file that isn't directly accessible (via abstract: true). Here's an example...
.state('standard', {
url: '/standard',
abstract: true,
templateUrl: '/tmpl/standard.html',
controller: 'SharedController'
},
})
.state('standard.page', {
url: '/:page',
resolve: {
page: function($stateParams) {
...
},
},
views: {
'content': {
templateUrl: '/tmpl/page',
controller: 'controllercontent'
},
'sideMenu': {
templateUrl: '/tmpl/menu',
controller: 'controllermenu',
}
}
});
In your tmpl/standard.html file, make sure this exists somewhere within the file:
<div ui-view="sideMenu">
<div ui-view="content">
Hope this points you in the right direction.