These are my state definitions:
$stateProvider
.state('schoolyears', {
url: '/schoolyears',
templateUrl: '../views/schoolyears.html',
controller: 'SchoolyearsController'
})
.state('schoolyears.selected', {
url: '/:schoolyearId'
})
Inside the SchoolyearsController I call $state.go when the selection of a row in the datagrid changes:
$scope.myOptions = {
data: 'myData',
multiSelect: false,
selectedItems: [],
afterSelectionChange: function (rowItem) {
if (rowItem.selected) {
$state.go('schoolyears.selected({ schoolyearId:' + rowItem.entity.schoolyearId + '}');
}
}};
Nothing happens in the url because in my browser console I have this error:
Error: Could not resolve 'schoolyears.selected({ schoolyearId:43}' from state 'schoolyears'
What I want is that the url changes to:
/#/schoolyears/43
Why can I not change the url?
Inside the SchoolyearsController change:
afterSelectionChange: function (rowItem) {
if (rowItem.selected) {
$state.go('schoolyears.selected({ schoolyearId:' + rowItem.entity.schoolyearId + '}');
}
}};
to:
afterSelectionChange: function (rowItem) {
if (rowItem.selected) {
$state.go('schoolyears.selected',{ schoolyearId: rowItem.entity.schoolyearId });
}
}};
As $state.go can be overloaded with two parameters in this instance, for more information please see the api reference
Related
I am currently on the main page after invoking
http://localhost:8199/#/iceberg-ui
I have a state called iceberg.reconcreate as defined below.
But when I try to invoke $state.go('iceberg.reconcreate') on the click of a button, I get the error that state is not defined.
angular-ui-router.js:982 Uncaught Error: No such state undefined at
Object.transitionTo (angular-ui-router.js:982) at Object.go
(angular-ui-router.js:973) at HTMLAnchorElement.
(angular-ui-router.js:1383) at HTMLAnchorElement.dispatch
(jquery.js:4641) at HTMLAnchorElement.elemData.handle (jquery.js:4309)
ROUTING
routingSetup.$inject = ['$stateProvider', '$urlRouterProvider'];
function routingSetup($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/iceberg-ui");
$stateProvider
.state('iceberg', {
url: "/iceberg-ui",
templateUrl: "app/iceberg/iceberg.view.html",
controller: 'IcebergController as icebergCtrl'
})
.state('iceberg.reconlist', {
templateUrl: "app/iceberg/recon/list/recon.list.view.html",
controller: 'ReconListController as reconListCtrl'
})
.state('iceberg.reconcreate', {
templateUrl: "app/iceberg/recon/create/recon.create.view.html",
controller: 'ReconCreateController as reconCreateCtrl'
})
.state('iceberg.recondetails', {
templateUrl: "app/iceberg/recon/details/recon.details.view.html",
controller: 'ReconDetailsController as reconDetailsCtrl'
})
}
Controller
(function() {
'use strict';
var myApp = angular.module('iceberg.recon');
myApp.controller('ReconListController', ReconListController);
ReconListController.$inject = ['ReconListService', '$state'];
function ReconListController(ReconListService, $state) {
var vm = this;
function getReconciliationList() {
return {
load: function(loadOptions) {
var reconList = ReconListService.getReconciliationList();
return {
data: reconList,
totalCount: reconList.length
};
},
update: function(key, values) {
console.log("calling the UPDATE GRID");
//Do Nothing, this method is required else the framework throws an error
}
};
}
vm.createNewRecon = {
text: "Create New Reconciliation",
icon: "plus",
type: "success",
height: "45px",
onClick: function(e) {
$state.go('iceberg.reconcreate');
}
};
}
}());
UPDATE - Updated with controller details
Sorry folks, that was an oversight from my end. I had a ui-sref defined with the incorrect name and all this while I was thinking it was getting called as a onclick event. My bad, apologies for the same.
This is my code.
.state('appSetting.studentList', { url: '/student', views: { 'list#appSetting': { templateUrl: appUrl + '/Student/List', controller: 'StudentCtrl' } } })
.state('appSetting.studentList.details', { url: '/:studentId', views: { 'details#appSetting': { templateUrl: appUrl + '/Student/Edit', controller: 'StudentEditCtrl' } } })
.state('appSetting.employeeList', { url: '/employee', views: { 'list#appSetting': { templateUrl: appUrl + '/Employee/List', controller: 'EmployeeCtrl' } } })
.state('appSetting.employeeList.details', { url: '/:employeeId', views: { 'details#appSetting': { templateUrl: appUrl + '/Employee/Edit', controller: 'EmployeeEditCtrl' } } })
I have a add button on layout , when user click the add button call the following function.
$scope.gotoAdd = function () {
if ($state.current.name.indexOf(".details") == -1) {
$state.go($state.current.name + ".details")
}
else {
var paramId = $state.current.url.slice(2);
$state.go($state.current.name, ({ studentId: "", reload: true }));
}
};
In the above code working fine, but when open employee page user click add button i want to empty of employeeId parameter. I have number of links so if condition is using lengthy process. The above variable paramId dynamically changed (one time "studentId" , "employeeId" ,..............) depends on current state.
I tried the following code but not working because paramId contains string value
$state.go($state.current.name, ({ paramId: "", reload: true }));
Why are you putting the second parameter in '( )' in $state.go().
Try
$state.go($state.current.next, {}, {reload: true});
or
$state.go($state.current.next, {paramId: ""}, {reload: true});
$scope.gotoAdd = function () {
if ($state.current.name.indexOf(".details") == -1) {
$state.go($state.current.name + ".details")
}
else {
for (var prop in $stateParams) {
if ($stateParams.hasOwnProperty(prop)) {
$stateParams[prop] = '';
}
}
$state.go($state.current.name,$stateParams, { reload: true });
}
};
$state.go can take an inherit boolean parameter that serve exactly for this purpose.
As of UI router 0.2.15 -probably an old version, the documentation states
inherit - {boolean=true}, If true will inherit url parameters from current url.
In fact, it reset not only url parameters, but all $stateParams to their default, like what they are in state definition.
This will keep only state params as passed through the params object and all other are set to default or deleted.
$state.go('target.state', params, {inherit: false});
I am having trouble passing some data to the stateprovider using $state.go(). Here is the sample code that we have been using.
$stateProvider.state('socialform', {
url: "/socialform?webcontent",
templateUrl: "base_template/_Sends.html?",
data: { pageTitle: 'Social & Website Publishing' },
resolve: {
callPreRenderServices: callPreRenderServices
}
});
$scope.isWebContent = function(status) {
if(status) {
$state.go('socialform', {webcontent:true});
}
else {
$state.go('socialform');
}
};
Basically, what we need to be doing is to pass a title variable to $state.go() so that it will replace the pageTitle to whatever is the value of the passed variable.
From the code above to this:
$stateProvider.state('socialform', {
url: "/socialform?webcontent",
templateUrl: "base_template/_Sends.html?",
data: { pageTitle: title },
resolve: {
callPreRenderServices: callPreRenderServices
}
});
$scope.isWebContent = function(status) {
if(status) {
$state.go('socialform', {webcontent:true, title:"some title"});
}
else {
$state.go('socialform', {title:"another title"});
}
};
You could use a service :
module.service('titleService', function() {
this.title = null;
});
// ... inject titleService in the calling controller ...
$scope.isWebContent = function(status) {
if(status) {
titleService.title = 'Some Title'
$state.go('socialform');
}
else {
titleService.title = 'Another Title'
$state.go('socialform');
}
};
Then, you can either inject it in via custom data or, via the resolve function :
// ... inject before route definition, via dependency injection
data = { title: titleService.title };
$stateProvider.state('socialform', {
url: "/socialform?webcontent",
templateUrl: "base_template/_Sends.html?",
// like this
data: data,
resolve: {
callPreRenderServices: callPreRenderServices
// Or you can resolve your title from your service
// and use pageTitle in your controller
pageTitle: ['titleService', function(titleService) {
return titleService.title;
}]
}
});
You could also pass it as a $state parameter :
$stateProvider.state('socialform', {
url: "/socialform/:webcontent/:title",
// ...
});
// ...
$state.go('socialform', {webcontent: 'something', title: 'some other thing'});
I'm having an issue trying to pass a parameter object to a state using stage.go().
Here is my state definition:
.state('drillhole.ddhinttype', {
url: '/ddhinttype',
templateUrl: VIRTUAL_DIR_PATH + '/App/Views/drillholemanager/drillhole/tabddhinttype.html?v=' + fileVer,
controller: 'DrillHoleDdhIntTypeController',
params: { name: null, description: null }
})
And here is my controller:
try {
angular.module('centric.drillhole.manager');
} catch (e) {
angular.module('centric.drillhole.manager', ['app.config', 'ui.router', 'kendo.directives', 'ui.bootstrap', 'ngCookies', 'centric.common', 'centric.notification', 'pascalprecht.translate', 'centric.security', 'centric.app.settings']);
}
angular.module('centric.drillhole.manager').controller('DrillHoleDdhIntTypeController', ['$scope', 'CentricUIHelper', 'NumberHelper', 'DrillHoleManagerService', 'app.config', '$stateParams',
function ($scope, uihelper, numberHelper, service, appconfig, $stateParams) {
$scope.loading = false;
$scope.isbusy = function () {
return $scope.loading || $scope.$parent.loading;
}
var load = function () {
var hello = $stateParams.name;
var hello2 = $stateParams.description;
};
load();
}]);
And I'm calling the state like so:
$state.go('drillhole.ddhinttype', { name: tab.params.name, description: tab.params.description });
In my controller the name and description properties are always null.
Not sure what I'm missing here. Any ideas?
If you put the params in your url you will be able to access it in controller using $stateParams
.state('drillhole.ddhinttype', {
url: '/ddhinttype/:name/:description',
templateUrl: VIRTUAL_DIR_PATH + '/App/Views/drillholemanager/drillhole/tabddhinttype.html?v=' + fileVer,
controller: 'DrillHoleDdhIntTypeController',
params: { name: null, description: null }
})
You can read more about url routing here: https://github.com/angular-ui/ui-router/wiki/url-routing
Try this in the state definition:
params: { name: undefined, description: undefined }
or this:
params: ['name', 'description']
I feel like I should post the final result. I have decided to pass the parameter in the URL so that I can re-use the same controller for several tabs which each have the same functionality but against different tables in the DB.
Here is the part of my base controller which creates the tabs (CoreLogController.js):
service.getDrillHoleIntervalTypes()
.success(function (res) {
$scope.data.drillHoleIntervalTypes = res;
for (var i = 0; i < $scope.data.drillHoleIntervalTypes.length; i++) {
// add the tab and set it as active if we're in the correct $state
$scope.dynamictabs.push({ heading: $scope.data.drillHoleIntervalTypes[i].Name, route: 'drillhole.ddhinttype', params: { ddhinttype: $scope.data.drillHoleIntervalTypes[i].Name }, active: ($scope.$state.params.ddhinttype == $scope.data.drillHoleIntervalTypes[i].Name) });
}
})
.error(function (error) {
uihelper.showError(error);
});
And here is the relevant HTML portion where the tabs are shown (corelog.html):
<tabset>
<tab ng-repeat="t in statictabs" heading="{{t.heading}}" ui-sref="{{t.route}}" active="t.active"></tab>
<tab ng-repeat="t in dynamictabs" heading="{{t.heading}}" ui-sref="drillhole.ddhinttype({ddhinttype: '{{t.params.ddhinttype}}'})" active="t.active"></tab>
</tabset>
And here is where I define the state (app.js):
.state('drillhole.ddhinttype', {
url: '/ddhinttype/{ddhinttype}',
templateUrl: VIRTUAL_DIR_PATH + '/App/Views/drillholemanager/drillhole/tabddhinttype.html?v=' + fileVer,
controller: 'DrillHoleDdhIntTypeController',
params: { ddhinttype: null }
})
I now get access to the ddhinttype variable on each instance of the controller (DrillHoleDdhIntTypeController.js) which tells it which table to perform operations against.
Since ddhinttype is also contained the URL the user can create a bookmark which will bring them right back to the same tab even though they are dynamically generated.
In Angular ui router, when $state.go("main.loadbalancer.readonly"); is ran after main.loadbalancer.readonly has been previously activated, my resolve: {} is not being evaulauted/executed. The resolve is simply bypassed..I have verified this with the console.log($state.current.data['deviceId']); not showing.
angular.module("main.loadbalancer", ["ui.bootstrap", "ui.router"]).config(function($stateProvider) {
return $stateProvider.state("main.loadbalancer", {
url: "device/:id",
views: {
"content#": {
templateUrl: "loadbalancer/loadbalancer.html",
controller: "LoadBalancerCtrl"
}
}
}).state("main.loadbalancer.vips", {
resolve: {
isDeviceReadOnly: function($state) {
console.log($state.current.data['deviceId']);
if (!$state.current.data['deviceId']) {
console.log("pimp");
$state.go("main.loadbalancer.readonly");
}
}
},
url: "/vips",
templateUrl: "loadbalancer/vip-table.html",
controller: "VipListCtrl"
}).state("main.loadbalancer.readonly", {
url: "/readonly",
templateUrl: "loadbalancer/readonly.html",
controller: "ReadonlyCtrl"
});
});
Controller code:
submit = function() {
$state.current.data = { deviceId: false };
return LoadBalancerSvc.searchDevice($scope.searchInput.value).get().then(function(lb) {
console.log(lb.ha_status);
if (lb.ha_status == "secondary") {
console.log("hi");
$state.current.data['deviceId'] = false;
$state.go("main.loadbalancer.readonly"); //WHEN THIS IS RAN A SECOND TIME
AFTER STATE HAS BEEN ACTIVE BEFORE
$state.deviceReadonly = true
} else {
$state.current.data['deviceId'] = lb.id;
$state.deviceReadonly = false;
SearchSvc.updateDeviceNumber(lb.id);
$state.go("main.loadbalancer.vips", {id: lb.id});
console.log("bye");
}
});
};
I can only guess that since main.loadbalancer.vips has been activated previously, then to ui router it means once resolved always resolved. How can I make it to where each time the state is activated with $state.go("main.loadbalancer.readonly") resolve will be evaluated?
Note: I have also tried $state.go("main.loadbalancer.readonly", { reload: true }); to no success.
It seems that 'transitionTo' works instead.
if (lb.ha_status == "secondary") {
$state.current.data['deviceId'] = false;
$state.transitionTo("main.loadbalancer.readonly", {}, { reload: true });
$state.deviceReadonly = true
}