Working on angular single page application.
I am trying this...
.state('one-category-product-list', {
url: '/products/:category/:category_id',
views: {
'': {
templateUrl: './view/single-category-product.html',
controller: 'ProductsController'
},
nav:{
templateUrl: function() {
if (authenticate() == 'customer') {
return './view/template/nav-login.html';
}
return './view/template/nav.html';
}
},
footer:{
templateUrl: './view/template/footer.html'
}
}
})
the issue with me if a user will not pass the category_id there or directly enters the URL without last parameter like www.example.com/product/category/ then it takes parameters category_id: "". How to restrict this.
Try this out:
.state('one-category-product-list', {
url: '/products/:category/:category_id',
views: {
'': {
templateUrl: './view/single-category-product.html',
controller: 'ProductsController'
},
nav: {
templateUrl: function () {
if (authenticate() == 'customer') {
return './view/template/nav-login.html';
}
return './view/template/nav.html';
}
},
footer: {
templateUrl: './view/template/footer.html'
}
},
resolve: {
data:($stateParams,$state, $q) => {
if(!$stateParams.category_id) {
$state.go('my-otherwise-state');
return $q.reject('No state params');
}
}
}
})
Related
I have simple hierarchical state:
angular
.module('App.Module.Suppliers', [])
.config(function($stateProvider) {
return $stateProvider
.state('suppliers', {
url: '/suppliers',
views: {
main: {
templateUrl: 'views/layouts/wrapper.html'
}
}
})
.state('suppliers.edit', {
url: '/:id',
views: {
entity_view: {
templateUrl: 'views/layouts/foo.html'
}
}
})
.state('suppliers.edit.details', {
url: '/edit',
views: {
entity_sub_view: {
controller: function () {
this.foo = {bar: "TEST HEADER"};
},
controllerAs: 'vm',
templateUrl: 'views/layouts/main.html'
}
}
});
});
main and entity_view views are generic for all entities and only entity_sub_view changes with core information.
Now in entity_view I want to use some value like <h2>{{vm.foo.bar}}</h2> but it seems that I can't access vm inside these parent states.
Is there a way to pass this and other parameters to parent states to use?
So I found solution that fits my need. Basically you can set controllerAs to top-most state and access it via $scope:
angular
.module('App.Module.Suppliers', [])
.config(function($stateProvider) {
return $stateProvider
.state('suppliers', {
url: '/suppliers',
views: {
main: {
templateUrl: 'views/layouts/wrapper.html'
controller: function () {
this.foo = null;
}
controllerAs: 'mainCtrl'
}
}
})
.state('suppliers.edit', {
url: '/:id',
views: {
entity_view: {
templateUrl: 'views/layouts/foo.html'
}
}
})
.state('suppliers.edit.details', {
url: '/edit',
views: {
entity_sub_view: {
controller: function () {
this.foo = {bar: "TEST HEADER"};
},
controllerAs: 'vm',
templateUrl: 'views/layouts/main.html'
}
}
});
});
And in some controller do
this.$scope.mainCtrl.foo = {bar: "TEST HEADER"};
In view
{{mainCtrl.foo.bar}}
This is my config:
.state('index.oz', {
abstract: true,
url: '/oz',
views: {
'mainView#': {
templateUrl: "Views/oz/oz.html",
controller: 'ozController'
}
}
})
.state('index.iz.a', {
url: '/a/:id',
params: {
id: {
value: null,
squash:true
}
},
views: {
'ozTypeView': {
templateUrl: "Views/oz/a.html",
controller: "ozaController"
}
}
})
.state('index.oz.b', {
url: '/b/:id',
params: {
id: {
value: null,
squash:true
}
},
views: {
'ozTypeView': {
templateUrl: "Views/oz/ozb.html",
controller: 'ozbController'
}
}
});
My desired urls are:
/oz/a
/oz/b
/oz/a/45
/oz/b/12
How can I make url in each child state so that I don't have to in each state write following piece fo code:
params: {
id: {
value: null,
squash:true
}
}
More spedific, can I somehow put that piece of code inside parent abstract state, or maybe even define parameter id inside parent state, but keeping my desired urls as mentioned above? Basicly, I'll have couple child states and I don't want for each state repeat same params code.
I guess directly you cant, but you can reduce code duplication like this:
function stateWithId(name, cfg) {
cfg.url += '/:id';
if (!cfg.params) {
cfg.params = {};
}
cfg.params.id = {
value: null,
squash:true
};
$stateProvider.state(name, cfg);
}
stateWithId('index.iz.a', {
url: '/a',
views: {
'ozTypeView': {
templateUrl: "Views/oz/a.html",
controller: "ozaController"
}
}
});
stateWithId('index.iz.b', {
url: '/b'
});
So I have my login screen where I do a Facebook login (this works perfect) and upon success of FB login it should go to another view. I try to achieve this with
$state.go("app.start")
But its not working. It just stays on the login view. Not sure why my $state.go is not working ...
My controller for the login button:
angular.module('MovieBankUser.controllers', [])
.controller('LoginCtrl', function($scope, LoginService, $state) {
$scope.loggingIn = false;
$scope.login = function () {
if (!$scope.loggingIn) {
$scope.loggingIn = true;
LoginService.loginUser().then(function () {
$scope.loggingIn = false;
//$window.location.href = "#/app/start"
$state.go('app.start');
//console.log("TEST TEST");
});
}
}
});
Part of my app.js code for the routing:
// Routes
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'views/login/login.html',
controller: 'LoginCtrl'
})
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'components/sidebar_menu/menu.html',
controller: 'AppCtrl'
})
.state('app.start', {
url: '/start',
views: {
'menuContent': {
templateUrl: 'views/start/start.html',
controller: 'MovieCtrl'
}
}
})
.state('app.trending', {
url: '/trending',
views: {
'menuContent': {
templateUrl: 'views/trending/trending.html',
controller: 'MovieCtrl'
}
}
})
.state('app.trending-detail', {
url: '/trending/:id',
views: {
'menuContent': {
templateUrl: 'views/trending/trending_detail.html',
controller: 'MovieDetailCtrl',
resolve: {
movie: function($stateParams, MovieService) {
return MovieService.getMovieById($stateParams.id)
},
trailer: function($stateParams, MovieService) {
return MovieService.getTrailerById($stateParams.id)
},
cast: function($stateParams, MovieService) {
return MovieService.getCastCrewInfo($stateParams.id)
}
}
}
}
})
.state('app.outnow', {
url: '/outnow',
views: {
'menuContent': {
templateUrl: 'views/out_now/outnow.html',
controller: 'MovieCtrl'
}
}
})
.state('app.outnow-detail', {
url: '/outnow/:id',
views: {
'menuContent': {
templateUrl: 'views/out_now/outnow_detail.html',
controller: 'MovieDetailCtrl',
resolve: {
movie: function($stateParams, MovieService) {
return MovieService.getMovieById($stateParams.id)
},
trailer: function($stateParams, MovieService) {
return MovieService.getTrailerById($stateParams.id)
},
cast: function($stateParams, MovieService) {
return MovieService.getCastCrewInfo($stateParams.id)
}
}
}
}
})
.state('app.comingsoon', {
url: '/comingsoon',
views: {
'menuContent': {
templateUrl: 'views/coming_soon/comingsoon.html',
controller: 'MovieCtrl'
}
}
})
.state('app.comingsoon-detail', {
url: '/comingsoon/:id',
views: {
'menuContent': {
templateUrl: 'views/coming_soon/comingsoon_detail.html',
controller: 'MovieDetailCtrl',
resolve: {
movie: function($stateParams, MovieService) {
return MovieService.getMovieById($stateParams.id)
},
trailer: function($stateParams, MovieService) {
return MovieService.getTrailerById($stateParams.id)
},
cast: function($stateParams, MovieService) {
return MovieService.getCastCrewInfo($stateParams.id)
}
}
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/login');
});
I'm wondering weather I can join two routes into one - add and edit.
Here are my states:
.state('app.topics.add', {
url: 'add/',
views: {
'page#app': {
templateUrl: 'app/sites/topics/add.html',
controller: 'topicsaddCtrl'
}
}
})
.state('app.topics.details', {
url: '{topic_id:[0-9]+}/',
views: {
'page#app': {
templateUrl: 'app/sites/topics/details.html',
controller: 'topicsdetailsCtrl'
}
}
})
.state('app.topics.details.edit', {
url: 'edit/',
views: {
'page#app': {
templateUrl: 'app/sites/topics/add.html',
controller: 'topicsaddCtrl',
}
}
})
topic/add/ - adding topic
topic/2/ - details of topic
topic/2/edit/ - editing topic
But state for add and edit are using the same templates and controllers. Can I simplyfy states?
You can use stateParams https://github.com/angular-ui/ui-router/wiki/URL-Routing
.state('app.topics.add', {
url: ':method/:id',
views: {
'page#app': {
templateUrl: 'app/sites/topics/add.html',
controller: 'topicsaddCtrl',
}
},
resolve: {
formData: ['$stateParams', 'topicSvc', function ($stateParams, topicSvc) {
if ($stateParams.method === 'add') {
return {}; //return empty object if you creating topic
} else if ($stateParams.method === 'edit' && $stateParams.id) {
return topicSvc.getDetail($stateParams.id); //get topic data from topicSvc service
}
}]
}
})
Also you can inject $stateParams to your controller and access its 'method' and 'id' property.
How come this Inherited Custom Data data is not accessible in the child state main.loadbalancer.vips in the resolve: {} function hello?
angular.module("main.loadbalancer", ["ui.bootstrap", "ui.router"]).config(function($stateProvider) {
return $stateProvider.state("main.loadbalancer", {
data: { readonly : false },
url: "device/:id",
views: {
"content#": {
templateUrl: "loadbalancer/loadbalancer.html",
controller: "LoadBalancerCtrl"
}
}
}).state("main.loadbalancer.vips", {
url: "/vips",
templateUrl: "loadbalancer/vip-table.html",
resolve: {
hello: function(data) {
console.log(data);
}
},
controller: "VipListCtrl"
})
That data should be accessible in the $state object if you inject it ($state):
$state.$current.data.readonly
I had to use this.data...
}).state("main.loadbalancer.vips", {
url: "/vips",
templateUrl: "loadbalancer/vip-table.html",
resolve: {
hello: function() {
console.log(this.data);
}
}