Im using angular and angular router-ui. I want to make use of dynamic url params.
This is how Im using it:
.state('index.domain', {
url: '/domain',
template: "<div ui-view> Home Domain page </div>"
})
.state('index.domain.id', {
url: '/:domainId',
resolve: {
domainId: function($stateParams){
return $stateParams.domainId;
}
},
templateUrl: "./development/administration/domain.html",
controller: function(domainId){
console.log(domainId);
}
})
Im calling the routing with the following invocation:
$state.go('index.domain.id', {"domainId": domainId});
It DOES execute the resolve and $stateParams get an object with domainId. Despite of that it does not get into the controller. The URL/:domainId does not changed either.
If I change in the browser the URL to point to URL/RANDOM_DOMAIN_ID (where RANDOM_ID is a domainId valid number) it executes the resolve and goes to the controller.
Am I missing something on the $state.go call?
There is a working plunker
I used the above state def as is:
.state('index', {
url: '/index',
template: "<div ui-view> Index </div>"
})
.state('index.domain', {
url: '/domain',
template: "<div ui-view> Home Domain page </div>"
})
.state('index.domain.id', {
url: '/:domainId',
resolve: {
domainId: function($stateParams){
return $stateParams.domainId;
}
},
templateUrl: "development/administration/domain.html",
controller: function(domainId){
console.log(domainId);
}
})
And made just few adjustments in the calling side - and this is working:
<a ui-sref="index.domain.id({domainId: 1})">...
<button ng-click="$state.go('index.domain.id', {domainId: 22});">...
Check it here
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 am using WordPress rest API and I have states in my AngularJS app as below:
.state('public.blog', {
abstract: true,
url: '/blog',
template: '<ui-view/>',
})
.state('public.blog.home', {
url: '/',
templateUrl: 'public/blog.html',
controller: 'PublicBlogCtrl',
controllerAs: 'vm',
})
.state('public.blog.post', {
url: '/:slug',
templateUrl: 'public/blog.post.html',
controller: 'PublicBlogPostCtrl',
controllerAs: 'vm',
})
And for example i have an article like 'http://example.com/blog/what-is-angularjs'. It's work fine when I clicking on a link in my application like this:
<a ui-sref="public.blog.post({ slug: post.slug })">
But the problem is when I writing the URL 'http://example.com/blog/what-is-angularjs' directly in browser address bar. When I do this, angular can't handle URL and recognize it as a wrong URL which doesn't match with any state, then it looks for $urlRouterProvider.otherwise('/404'); and shows my 404 - Not Found Page.
So whats the wrong?
UPD #1
When I send slug post's slug as parameter the issue occurs, but when I use post's ID to retrieve post, it's work fine. So I think some thing is wrong in wp-api's slug.
UPD #2
The controller looks like this:
function PublicBlogPostCtrl($scope, $stateParams, WPService) {
var vm = this;
WPService.getPost($stateParams.slug).success(function(res) {
$scope.post = res[0];
}).error(function(err) {
console.error(err);
});
}
app.controller('PublicBlogPostCtrl', PublicBlogPostCtrl);
And the WPService.getPost as below:
WPService.getPost = function(slug) {
return $http.get('wp-json/wp/v2/posts/?filter[name]=' + slug).success(function(res, status, headers) {
return res;
}).error(function(err) {
return err;
});
};
Could it be the url for blog posts? instead of /:slug, should it be /blog/:slug?
It would work from clicking on a link because you supply the state and slug directly instead of via a URL.
I'd like my Angular website to get several routes using ui-router, which are:
/ which renders landing.html
/howto which renders howto.html
I tried the following, with no success:
$stateProvider
.state('landing', {
url: '/',
templateUrl: 'views/landing.html',
controller: 'LandingCtrl',
data : { pageTitle: 'Landing' }
})
.state('howto', {
url: '/howto',
templateUrl: 'views/howto.html',
controller: 'HowToCtrl',
data : { pageTitle: 'HowTo' }
});
I can access landing.html on localhost/ but cannot access /howto, I get the message Cannot GET /howto. Do you have any idea?
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" :-)