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 + "/";
Related
For example, on the last state on the below code I want to get the value of "category" URL parameter so that I can use it to retrieve some from the database
var app = angular.module("myApp",["ui.router"]);
app.config(function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise("/");
$stateProvider
.state("main", {
url: "/",
views: {
"slider": {
templateUrl: "slider.html"
},
"departments": {
templateUrl: "departments.html"
},
"brands": {
templateUrl: "brands.html"
}
}
})
.state("cart", {
url: "/cart",
views: {
"cart": {
templateUrl: "../account/cart.php"
}
}
})
.state("department", {
url: "/department/:category",
views: {
"department": {
templateUrl: "department.php"
}
}
});
});
Create a controller, pass stateParams and instantiate the controller within the views of the last state
.state("department", {
url: "/department/:category",
views: {
"department": {
templateUrl: "department.php",
controller: "myController"
}
}
});
});
app.controller('myController', function($stateParams) {
var param = $stateParams.category;
document.getElementById("category").value = param;
});
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))/
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'
});
I am working on an AngularJS app. I've gotten quite a bit done but am stuck trying to implement a resolve using ui-router and uiBreadcrumbs. So here is the problem, how do I implement a resolve which can work well with magnification, the same way controllers are implemented? I have included sample code below for brevity from uiBreadcrumbs. Look at the last state home.userList.detail.
angular.module('yourModule').config(function($stateProvider) {
$stateProvider
.state('home', {
url: '/',
views: {
'content#': {
templateUrl: ...
}
},
data: {
displayName: 'Home'
}
})
.state('home.usersList', {
url: 'users/',
views: {
'content#': {
templateUrl: ...
}
},
data: {
displayName: 'Users'
}
})
.state('home.userList.detail', {
url: ':id',
views: {
'content#': {
templateUrl: ...
}
},
data: {
displayName: '{{ user.firstName }} {{ user.lastName | uppercase }}'
}
resolve: {
user : function($stateParams, userService) {
return userService.getUser($stateParams.id);
}
}
});
Wrap the function in an array object just like a controller:
resolve: {
user : [
'$stateParams', 'userService',
function($stateParams, userService) {
return userService.getUser($stateParams.id);
}
]
}
I am using ui.router to handle my app routing, currently my app is small online a couple routes. As of right now they go into app.config, i'd like to spilt out each route configuration based on feature, for example this feature is a for a "Promotion" SPA, how can I go about doing this so I won't clutter my initial app.config js file?
$stateProvider
.state('promotion', {
controller: 'PromotionsController',
url: '',
views: {
"list": {
controller: 'PromotionsController',
templateUrl: templatesRoot + 'Promotion/promotion-list.html'
},
"editor": { template: "Welcome" }
}
})
.state('promotion-edit',
{
url: '/edit/{id}',
views: {
"list": {
controller: 'PromotionsController',
templateUrl: templatesRoot + 'Promotion/promotion-list.html'
},
"editor": {
controller: ['$scope', '$stateParams', 'promotionService', function ($scope, $stateParams, promotionService) {
$scope.promotion = promotionService.getPromotion($stateParams.id)
$scope.savePromotion = function () {
// save the promotion
promotionService.savePromotion($scope.promotion, function (data, responseHeaders) {
if (!data.Success) {
toaster.pop({
type: 'error',
title: 'Error',
body: data.Message,
showCloseButton: true
});
} else {
toaster.pop({
type: 'success',
title: "Success",
body: "Successfully saved the promotion",
showCloseButton: true
});
}
});
};
}],
templateUrl: templatesRoot + 'Promotion/promotion-edit.html'
}
}
}
)
.state('promotion-create',
{
url: '/create',
views: {
"list": {
controller: 'PromotionsController',
templateUrl: templatesRoot + 'Promotion/promotion-list.html'
},
"editor": {
controller: 'PromotionsController',
templateUrl: templatesRoot + 'Promotion/promotion-create.html'
}
}
}
)
Separate your routes into files. For example:
promotion.js
angular.module('AppName').config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
$stateProvider.state('promotion', {
controller: 'PromotionsController',
url: '',
views: {
"list": {
controller: 'PromotionsController',
templateUrl: templatesRoot + 'Promotion/promotion-list.html'
},
"editor": { template: "Welcome" }
}
})
}]);
Then in your index.html, reference this file:
<script src="pathToRoutes/promotion.js"></script>
After that you should be good to go.
Just put it in a separate files which contain only config blocks.
For example you can have:
app/scripts/app.js # not router configuration
app/scripts/routes/promotions.js # pomotions configuration
app/scripts/routes/featureN.js # n-th feature
app/scripts/routes/custom-states-provider.js
The last one you will need if you notice a lot of code duplication between the features and you want to make a custom wrapper around the ui router $stateProvider with utility functions. Of course there are other solutions to this problem.