How to activate a state and pass object to the new view? - angularjs

app.js:
$stateProvider.state('datasource', {
url: '/datasource',
templateUrl: 'views/datasource.html',
controller: 'datasourceController'
});
$stateProvider.state('datasourceList', {
url: '/datasource/:datasourceId',
templateUrl: 'views/datasource.list.html',
controller: 'datasourceController'
});
Then, I've a function activated onClick defined in (datasourceController)
$scope.submitSelected = function() {
if (angular.isDefined($scope.selectedSource)) {
$scope.datasource = dataSourcesService.find($scope.selectedSource.id);
$state.go('datasourceList', {datasourceId : datasource});
}
}
As I said, in my datasource.html view have an element click that triggers submitSelected() function
I can retrieve data successfully from my service based on ID when call it in function.
Problem is, i cant access the results (scope) of it in the view datasource.list.html after changing the state.

Add 'param' in state config
$stateProvider.state('datasource', {
url: '/datasource',
templateUrl: 'views/datasource.html',
controller: 'datasourceController'
});
$stateProvider.state('datasourceList', {
url: '/datasource/:datasourceId',
templateUrl: 'views/datasource.list.html',
params: ['index', 'anotherKey'],
controller: 'datasourceController'
});
And get values using $stateParams in another controller
app.controller('datasourceController', function($scope, $stateParams) {
var index = $stateParams.index;
var anotherKey = $stateParams.anotherKey;
});

Related

Is it possible to mix injected dependencies with custom arguments in AngularJS?

I'm using UI Bootstrap's $uibModal to create a modal. I'm also using UI Router 0.2.15, so what I want is a state opening in a new modal.
This is what I have in my config function:
$stateProvider
.state("mystate.substate1", {
url: '...',
template: '<div ui-view></div>',
onEnter: showFirstCustomModal
})
.state("mystate.substate2", {
url: '...',
onEnter: showSecondCustomModal
});
// End of calling code
function showFirstCustomModal($uibModal) {
var options = {
backdrop: 'static',
templateUrl: '...',
controller: 'Controller1',
controllerAs: 'controller'
};
$uibModal.open(options);
}
function showSecondCustomModal($uibModal) {
var options = {
backdrop: 'static',
templateUrl: '...',
controller: 'Controller2',
};
$uibModal.open(options);
}
The two modal methods above are very similar. I would like to replace them with a generic method:
$stateProvider
.state("mystate.substate1", {
url: '...',
onEnter: showGenericModal('some_template','SomeController1', 'alias1')
})
.state("mystate.substate2", {
url: '...',
onEnter: showGenericModal('some_other_template', 'SomeController2')
});
// End of calling code
function showGenericModal(templateUrl, controller, controllerAlias, $uibModal) {
var options = {
backdrop: 'static',
templateUrl: templateUrl,
controller: controller
};
if(!!controllerAlias) {
options.controllerAs: controllerAlias;
}
$uibModal.open(options);
}
I put the $uibModal as the last argument to avoid it getting reassigned. But I can't get this to work. The error I get is
Cannot read property 'open' of undefined
Also, I've been reading this and I know that you'll have to use the $injector in order to allow your service to be injected. But I supposed that's already handled by UI-Bootstrap.
Since $stateProvider is defined in config block, $uibModal can't be passed from there as a reference.
It is not possible to mix dependencies and normal arguments in Angular DI. For onEnter it should be a function that accepts the list of dependencies.
The code above translates to:
onEnter: showGenericModal('some_other_template', 'SomeController2')
...
function showGenericModal(templateUrl, controller, controllerAlias) {
return ['$uibModal', function ($uibModal) {
...
$uibModal.open(options);
}];
}
Or a better approach:
onEnter: function (genericModal) {
genericModal.show('some_other_template', 'SomeController2');
}
...
app.service('genericModal', function ($uibModal) {
this.show = function (templateUrl, controller, controllerAlias) {
...
$uibModal.open(options);
}
});
#estus answer correct, I don't know how I didn't saw the state: "For onEnter it should be a function that accepts the list of dependencies.".
However, I will let my answer here to provide another perspective. You can define a service to wrap up and organize correctly your code, in order to call a customized modal on onEnter state event:
angular.module('app').service('AppModals', AppModals);
// or use /** #ngInject */ aswell
AppModals.$inject = ['$uibModal'];
function AppModals($uibModal) {
this.open = function _generateModal(options) {
var defaultOptions = {
backdrop: 'static'
// Any other default option
};
return $uibModal.open(angular.extend({}, defaultOptions, options);
};
}
On the state definition:
$stateProvider
.state('app.state', {
url: '/state-modal',
template: '<ui-view></ui-view>',
controller: 'DummyCtrl',
controllerAs: 'dummy',
onEnter: appState_onEnter
});
// or use /** #ngInject */ aswell
appState_onEnter.$inject = ['$uibModal'];
function appState_onEnter(AppModals) {
AppModals.open({
templateUrl: 'modals/state-modal.html',
controller: 'DummyCtrl',
controllerAs: 'dummy'
});
}

How to add parameter in state `url` in angularjs

I am trying to add a parameter to my angular application. actually my app will dynamically called as :
"https://abc.ss.com/xx/sn=1234568505
to handle this state - in my $stateProvider - I am trying like this:
.state('serialCreateCase', {
url: '/sn=*', //but not working
templateUrl:'abxy.html',
controller: 'controllersss as ctrl',
}
})
But my URL is not capturing redirecting to default page. how to add the = parameter?
Try this:
.state('serialCreateCase', {
url: '^/sn={id}',
params: {
id: {}
},
templateUrl:'abxy.html',
controller: 'controllersss as ctrl',
}
That should match the url you're expecting.
Edit: answer has been updated to change it to required parameters.
Did you try this: http://benfoster.io/blog/ui-router-optional-parameters
Query Parameters
So that query parameters are mapped to UI Router's $stateParams object, you need to declare them in your state configuration's URL template:
state('new-qs', {
url: '/new?portfolioId',
templateUrl: 'new.html',
controller: function($scope, $stateParams) {
$scope.portfolioId = $stateParams.portfolioId;
}
})
You can then create a link to this state using the ui-sref attribute:
<a ui-sref="new-qs({ portfolioId: 1 })">New (query string)</a>
This will navigate to /new?portfolioId=1.
If you have multiple optional parameters, separate them with an &:
state('new-qs', {
url: '/new?portfolioId&param1&param2',
templateUrl: 'new.html',
controller: function($scope, $stateParams) {
$scope.portfolioId = $stateParams.portfolioId;
$scope.param1 = $stateParams.param1;
$scope.param2 = $stateParams.param2;
}
})
You could add params like this
state('serialCreateCase', {
url: '/xx?sn',
templateUrl: 'abxy.html',
controller: 'controllersss as ctrl',
}
})
The state ref will be
<a ui-sref="serialCreateCase({ sn: 1234568505 })">URL</a>

ui-router ignoring state params

I'm trying to implement a forgot password flow in my application that collects some information from the user and passes it through states.
After the user submits their employee ID and where they want a reset code sent to (email or phone), I send both of those to the token state:
$state.go("^.token", { employeeId: forgot.employeeid, resetType: forgot.resetType });
My router is pretty straightforward:
$stateProvider.state("authentication.forgot", {
url: "/login/forgot",
templateUrl: "partials/authentication/forgot.html",
controller: "ForgotController as forgot",
onEnter: function () { $(document).foundation(); }
});
$stateProvider.state("authentication.token", {
url: "/login/token",
templateUrl: "partials/authentication/token.html",
controller: "TokenController as token",
onEnter: function () { $(document).foundation(); }
});
And here is my token controller:
app.controller("TokenController", function ($state, $stateParams, $timeout, Authentication) {
console.log($stateParams);
});
In my token controller, $stateParams ends up being an empty object.
You are not specifying any parameter in the $stateProvider definition, put a url parameter or define the params parameter in the $stateProvider definition.
url: "/login/token",
params: { object: {} },
templateUrl: "partials/authentication/token.html",
Note than {} is the default value for object, in case no params are specified in the state transition, and you'll be able to access this via $sateParams.object
You have to declare the params that you are trying to access in the state declaration.
$stateProvider.state("authentication.token", {
url: "/login/token?employeeId:[a-zA-Z0-9]*&resetType:[A-Z]",
templateUrl: "partials/authentication/token.html",
controller: "TokenController as token",
onEnter: function () { $(document).foundation(); }
});
You would then be able to access these in your controller via $stateParams.

Angular ui-router resolve not working

I am trying to load a get service JSON function in the main state resolve function so I can store the data to a scope variable.
The account JSON information is relevant because all sub pages are essentially dependent on the information.
--
The below code is partially working. The account resolve function is being successfully called and even the $http returns a promise (state === 0 though). The issue is when the account function resolves the state.controller is never being called.
$stateProvider
.state('app',{
url: '/',
views: {
'header': {
templateUrl: '../views/templates/partials/header.html',
},
'content': {
templateUrl: '../views/templates/partials/content.html'
},
'footer': {
templateUrl: '../views/templates/partials/footer.html',
}
},
resolve: {
account: function($timeout, accountFactory){
//Comment
return $http({method: 'GET', url: '/account.json'});
}
},
controller: ['$scope', 'account', function($scope, account){
// You can be sure that promiseObj is ready to use!
$scope.data = account;
console.log('SCOPE!!!!!');
}],
})
.state('app.accessory', {
url: 'accessory',
views: {
'content#': {
templateUrl: '../views/accessory/listing.html',
controller: 'accessoryListingCtrl',
controllerAs: 'vm'
}
}
})
}]);
Your parent state config is not correct. When using multiple named views A controller does not belong to a state but to a view, so you should move your controller statement to the specific view declaration, or all of them if you need it everywhere.
See here: https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views
$stateProvider
.state('report',{
views: {
'filters': {
templateUrl: 'report-filters.html',
controller: function($scope){ ... controller stuff just for filters view ... }
},
'tabledata': {
templateUrl: 'report-table.html',
controller: function($scope){ ... controller stuff just for tabledata view ... }
},
'graph': {
templateUrl: 'report-graph.html',
controller: function($scope){ ... controller stuff just for graph view ... }
},
}
})
I don't know why the controller does not get called. But you can start by making sure that resolve always return data.
resolve: {
account: function($timeout, accountFactory){
//Comment
return $http({method: 'GET', url: '/account.json'})
.$promise.then(
function(data) { return data; },
function(error) { return error; });
}
}

How to get url parameters from controller in angular.js

so, in my app.js :
.state('app.packages', {
url: "/packages/:packagesId",
views: {
'menuContent' :{
templateUrl: "templates/packages.html",
controller: function ($stateParams) {
console.log($stateParams);
}
}
}
})
in browser console, it showing this :
Object {packagesId: "25242039"}
How do i access the $stateParams that hold the value of packagesId inside controller.js?
Currently doing it like this, but it is not working...
.controller('PlaylistCtrl', function($scope,$stateParams) {
$scope.getId = function(){
return $scope = $stateParams.packagesId ;
};
})
First off, I don't understand why you want to assign the id to the scope return $scope = $stateParams.packagesId;
Secondly, you have a controller PlaylistCtrl, so you need to set it for router state.
// you may try simple view first
.state('app.packages', {
url: "/packages/:packagesId",
templateUrl: "templates/packages.html",
controller: 'PlaylistCtrl'

Resources