How define url params inside state common for each child state - angularjs

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'
});

Related

How to modify url of a state in AngularJS ui-routes

I am on angular 1.6. Trying to override value of a ui-router state.
Initial states as follows :
$stateProvider.state('parent', {
abstract: true,
parent: 'ancestor',
url: '/parent',
data: {
authorities: [A,B]
},
views: {
'content#': {
templateUrl: 'app/scripts/myapp/module/parent.html'
}
}
})
.state('child', {
parent: 'parent',
abstract: true,
views: {
'tabs': {
templateUrl: 'app/scripts/myapp/module/submodule/child.html',
controller: 'ChildController',
controllerAs: 'childController'
}
}
})
.state('grandChild', {
parent: 'child',
url: '/{dataSource:(?:option1|option2|option3)}',
views: {
'body': {
templateUrl: 'app/scripts/myapp/module/submodule/grandchild.html',
controller: 'GrandChildController',
controllerAs: 'grandChildController'
},
},
resolve: {
groups: ['MyService', '$transition$', function (MyService, $transition$) {
var selectedSource = $transition$.params().dataSource ? $transition$.params().dataSource : 'option1';
return MyService.getGroups(selectedSource);
}]
}
})
Then in one of sub-implementation I am trying to override value of url - adding option4 for one of the state.
var states = $stateRegistry.deregister('grandChild');
$stateRegistry.register(states[0]);//There is one more child. For simplicity not showing here.
states[1].url.pattern = '/{dataSource:(?:option1|option2|option3|option4)}';
$stateRegistry.register(states[1]);
when I do following on 'grandChild'
$state.go('grandChild', {dataSource: 'option4'});
I get error as
Param values not valid for state 'grandChild'. Invalid params: [ dataSource ]
when I inspect $state
I see something weird.
$state.$current.params.datasource.type.pattern = /(?:option1|option2|option3)/
$state.$current.url.pattern = "/{dataSource:(?:option1|option2|option3|option4)}"
$state.$current.url._compiled[0] = /((?:option1|option2|option3))/

Prevent URL's parameter can't be null in UI-Router

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');
}
}
}
})

angular routing: same url but conditional routing

Right now I have a route as follows:
.state('tab.simon', {
url: '/plan/:exerciseId', <== Notice here
resolve: {
authenticated: ['djangoAuth', function(djangoAuth){
return djangoAuth.authenticationStatus();
}],
},
views: {
'tab-plan': {
templateUrl: '/templates/simon.html',
controller: 'simonCtrl',
data: {
css: '/css/simon.css'
}
}
},
cache: false
})
The value for exerciseId could be 8/9/10/11/12 and for each such route i.e. /plan/8 or /plan/9 etc there is a separate controller and corresponding template and a css file.
Write now I had coded it as follows:
.state('tab.simon', {
url: '/plan/8',
resolve: {
authenticated: ['djangoAuth', function(djangoAuth){
return djangoAuth.authenticationStatus();
}],
},
views: {
'tab-plan': {
templateUrl: '/templates/simon.html',
controller: 'simonCtrl',
data: {
css: '/css/simon.css'
}
}
},
cache: false
})
.state('tab.pinpoint', {
url: '/plan/9',
resolve: {
authenticated: ['djangoAuth', function(djangoAuth){
return djangoAuth.authenticationStatus();
}],
},
views: {
'tab-plan': {
templateUrl: '/templates/pinpointReaction.html',
controller: 'pinpointCtrl',
data: {
css: '/css/pinpoint.css'
}
}
},
cache: false
})
This is not optimum and in this case I can not take advantage of $stateparams as with plan/:exerciseId
How can I handle this?
I do not know how technically it is possible, but logically i solved my problem.
Essentially, Each route has it's own controller so passing exerciseId as stateParam wasn't necessary as I initially thought. I could instead hardcode it in my controller like following:
$scope.gameType=9
var url = "https://127.0.0.1:8000/api2/games/get_game/" + $scope.gameType + "/";
instead of
var exerciseType = Number($stateParams.exerciseId);
var url = "https://127.0.0.1:8000/api/exercises/get_exercise/" + exerciseType + "/";

Angular UI Router - pass some params state in route, and some not?

I want to be able to pass some state params that will show up in the route, and some that won't.
It would be nice to be able to do this:
.state('widgetadmin.widgets.widget', {
url: '/widget/{widgetId}/{friendlyName}',
views: {
"sub#widgetadmin": {
controller: 'WidgetAdminController as vm',
templateUrl: 'widgetadmin/widgets/widget.tpl.html',
params: { widgetHref: null }
}
},
data:{ pageTitle: 'Edit Widget' }
}
Then pass it like this:
$state.go('widgetadmin.widgets.widget',
{widgetId: widget.id, friendlyName: slug, widgetHref: widget._links.self.href},
{reload: true});
But when I try to access it, it's undefined:
var something = $stateParams.widgetHref;
How can I pass some state params in route, and some not?
Needed to put the params in a different place:
.state('widgetadmin.widgets.widget', {
url: '/widget/{widgetId}/{friendlyName}',
views: {
"sub#widgetadmin": {
controller: 'WidgetAdminController as vm',
templateUrl: 'widgetadmin/widgets/widget.tpl.html'
}
},
data:{ pageTitle: 'Edit Widget' },
params: { widgetHref: null }
}

Angular UI Router - Access Custom Data in Children's Resolve {}

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);
}
}

Resources