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"];
}
})
Related
I have tried to implement angular js $state.go() with parameter. But the $state.go() works fine without parameter. But with parameter it didn't works. I already tried many examples but no way. I need to display the parameter in html view.
my state provider is,
$stateProvider
.state('home', {
url: '/',
views: {
'content#': {
templateUrl: 'content.html',
controller: 'dashCtrl'
}
},
params: {
obj: {
value:''
}
}
});
and controller is,
dashboard.controller('dashCtrl', function ($scope, $http, $state, $stateParams){
$state.go('dash_home', {obj: {value:'admin'}});
});
and my div is
<div>
<h1>welcome : {{value}} || {{obj.value}}</div>
what is the problem.?
You cannot use parameters directly in the HTML. You first have to add it to the scope (or virtual model if you use that), e.g.
$scope.obj = $state.current.params.obj
And you have to do it in the controller of the state that you are going to of course, not in those where you call $state.go
I found my mistakes. The correct code is,
$stateProvider
.state('home', {
url: '/',
views: {
'content#': {
templateUrl: 'content.html',
controller: 'dashCtrl'
}
},
params: {
value:''
}
});
controller is,
dashboard.controller('mycontroller',function($scope, $http, $state, $stateParams){
$scope.user=$state.params.registerData;
$scope.redirect=function()
{
$state.params.registerData='mycontent';
$state.go('dash_home', {registerData:$state.params.registerData});
}
});
thanks all.
I guess you can't use objects in params. Just replace
params: {
obj: {
value:''
}
}
to this:
params: {
value:''
}
and also: $state.go('dash_home', {obj: {value:'admin'}}); to $state.go('home', {value:'admin'});
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?
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" :-)
I have an Angular app with several nested controllers and views. I implemented infinite scrolling in it closely based on this tutorial for ngInfiniteScrolling: http://binarymuse.github.io/ngInfiniteScroll/demo_async.html
So I have a service that loads items into an array at $scope.content.items. Then there's an ng-repeat element that shows each result.
$scope.content = new Content()
$scope.content.loadMore( $scope.currentStream, 2 ) // this part is actually called in the HTML, but while debugging I've just done it in the controller
Now I want to implement search, and instead of making another search page, just have the items load in place of the current list of items. Basically to take the place of $scope.content.items.
So I built an identical controller, but now calling my search API. I use ng-change to see if someone has typed in the search box, then within the function that calls, do
$scope.search = function() {
$scope.content = new Search()
$scope.content.load( $scope.query )
}
I can see that this works in the console, that it replaces $scope.content.items, by doing this in the browser console:
var scope = angular.element($('[ng-controller=HomeController]')).scope()
scope.content.items
That shows me the array of objects I expect in each case (either before triggering ng-change="search()" or after). But the page itself does not update. It just shows the stuff from the Content() service.
Likewise, if I replace the above two lines from my controller with these below, it shows the content from the Search() service:
$scope.content = new Search()
$scope.content.load( 'thom' )
Long story short, I feel like the services and API work, but the page is not updating when I change the $scope.content.items array used by ng-repeat.
Here is the HTML
<div class="panel panel-item" ng-repeat="item in content.items" ng-hide="hideItem">
<h2 ng-hide=" item.stream == 'read' " data-ng-bind="item.title"></h2>
<a ng-click="openReaderModal( item )" class="cursor-pointer" ng-show=" item.stream == 'read' ">
<h2 data-ng-bind="item.title"></h2>
</a>
// ...
<div class="clearfix"></div>
</div>
Fixed it, somehow. Here is my routes from app.config() before:
$stateProvider
// ...
.state( 'app', {
url: '/app',
templateUrl: 'app/views/app.html',
controller: 'HomeController'
})
.state( 'app.home', {
url: '/main',
templateUrl: 'app/views/home.html',
controller: 'HomeController'
})
.state( 'app.profile', {
url: '/profile',
templateUrl: 'app/views/profile.html',
controller: 'ProfileController'
})
.state( 'app.read', {
url: '/read',
templateUrl: 'app/views/stream-content.html',
controller: 'HomeController'
})
.state( 'app.watch', {
url: '/watch',
templateUrl: 'app/views/stream-content.html',
controller: 'HomeController'
})
.state( 'app.listen', {
url: '/listen',
templateUrl: 'app/views/stream-content.html',
controller: 'HomeController'
})
And here's after:
$stateProvider
// ...
.state( 'app', {
url: '/app',
templateUrl: 'app/views/app.html',
controller: 'HomeController'
})
.state( 'app.home', {
url: '/main',
templateUrl: 'app/views/home.html'
})
.state( 'app.profile', {
url: '/profile',
templateUrl: 'app/views/profile.html',
controller: 'ProfileController'
})
.state( 'app.read', {
url: '/read',
templateUrl: 'app/views/stream-content.html'
})
.state( 'app.watch', {
url: '/watch',
templateUrl: 'app/views/stream-content.html'
})
.state( 'app.listen', {
url: '/listen',
templateUrl: 'app/views/stream-content.html'
})
And it works. If anyone can provide an explanation, I'll credit them the answer.
The routing in angular works like this.
When we provide a controller for the $stateProvider its actually considered as a new constructor (new keyword as in java) thus the data is re-initiated to defaults.
The new constructor will be the child to itself, to access the parent controller one can use the $parent
My setup
app/learning/learning.js
angular.module('meanApp')
.config(function($stateProvider) {
$stateProvider
.state('learning',{
templateUrl: 'app/learning/learning.html',
url: '/learning',
controller: 'LearnCtrl',
views: {
'list': {
templateUrl: 'app/learning/learning.list.html',
controller: function($scope){ }
},
'magic': {
templateUrl: 'app/learning/learning.magic.html',
controller: function($scope){ }
}
}
});
});
app/learning/learning.html
<h1>Learning</h1>
<div ui-view="list"></div>
<div ui-view="magic"></div>
app/learning/learning.list.html
<p>A list</p>
app/learning/learning.magic.html
<h2>Magic</h2>
when I navigate to /learning I get a blank page, I'm not sure what I'm doing wrong so any help would be greatly appreciated.
You shouldn't load the base template inside state when there are nested ui-view,
Define the base template inside views.
Route Code
angular.module('meanApp')
.config(function($stateProvider) {
$stateProvider
.state('learning',{
url: '/learning',
views: {
'': {
templateUrl: 'app/learning/learning.html',
controller: 'LearnCtrl'
},
'list#learning': { //you missed state name here
templateUrl: 'app/learning/learning.list.html',
controller: function($scope){ }
},
'magic#learning': { //you missed state name here
templateUrl: 'app/learning/learning.magic.html',
controller: function($scope){ }
}
}
});
});
This could Help you, Thanks.
The problem was that I was trying to load the base template inside state and I missed out the state name as Pankaj said, so the solution is...
angular.module('meanApp')
.config(function($stateProvider) {
$stateProvider
.state('learning',{
url: '/learning',
views: {
'': {
templateUrl: 'app/learning/learning.html',
controller: 'LearnCtrl'
},
'list#learning': { //you missed state name here
templateUrl: 'app/learning/learning.list.html',
controller: function($scope){ }
},
'magic#learning': { //you missed state name here
templateUrl: 'app/learning/learning.magic.html',
controller: function($scope){ }
}
}
});
});