How to pass params to target route using UI Router Tabs - angularjs

I am using UI Router Tabs for navigation/routing. There are three tabs [User, Address and Service]. Individual tab have their own state, url, controller and template.
How can I pass request params (saved object ID, firstname and lastname) from User tab [UserCtrl.js] to AddressCtrl.js and ServiceCtrl.js.
HOW CAN I ACHIEVE THIS?
What I have done so far?
app.js
'use strict';
var app = angular.module('xyzApp', [ 'ui.router','ngResource', 'ui.bootstrap', 'ui.router.tabs']);
app
.config(['$stateProvider', '$urlRouterProvider', '$httpProvider', '$interpolateProvider', '$locationProvider',
function($stateProvider, $urlRouterProvider, $httpProvider, $interpolateProvider, $locationProvider) {
// CSRF Support
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$urlRouterProvider.otherwise('/');
$stateProvider
.state('new', {
url: '/',
controller: 'MainCtrl',
templateUrl: 'partials/base.html'
})
.state('new.user', {
url: '/new/user',
controller: 'UserCtrl',
templateUrl: 'partials/user-tab.html'
})
.state('new.address', {
url: '/new/address',
controller: 'AddressCtrl',
templateUrl: 'partials/address-tab.html'
})
.state('new.service', {
url: '/new/service',
controller: 'ServiceCtrl',
templateUrl: 'partials/service-tab.html',
})
}]);
MainCtrl.js
'use strict';
app
.controller('MainCtrl', ['$scope', function($scope) {
// Inititalise the new personnel page tabs
$scope.initialise = function() {
$scope.go = function(state) {
$state.go(state);
};
$scope.personneltabinfo = [
{
heading: 'User',
route: 'new.user',
//params: {
// userId: $scope.userId
//},
},
{
heading: 'Address',
route: 'new.address',
},
{
heading: 'Service',
route: 'new.service'
}
];
};
$scope.initialise();
}]);
UserCtrl.js
'use strict';
app
.controller('UserCtrl', ['$scope', '$rootScope', '$http', '$compile', '$timeout', 'userServices',
function($scope, $rootScope, $http, $compile, $timeout, userServices) {
$scope.userId = '';
$scope.savePerson = function() {
console.log("This is userData:" + $scope.userData);
// user resource service
userServices.addUser($scope.userData)
.then(function(data) {
// pass $scope.userId to [Account and Service] routes view.
// pass firstname and secondname value to [Account and Service] routes view so it’s value can be shown on their panel-title.
$scope.userId = data.id;
toastr.success('Personnel ' + $scope.baseData.first_name + ' record saved into database');
}, function(data, status, headers, config) {
toastr.error('Field Error:' + " Please fill all fields mark with * ");
});
};
}]);
I'm angular beginner!

If I understand your question, you want to pass the data from a controller to another controller.
You can check on: Passing data between controllers in Angular JS?
You can use :
a service: https://docs.angularjs.org/guide/services,
$rootScope but that's not the best solution,
or the binding data between components: https://docs.angularjs.org/guide/component

Related

$state.go() not working with angular and onsenui

This is my app.js
var Myapp = ons.bootstrap('Myapp',[]);
document.addEventListener('deviceready', function () {
}, false)
controller.js :
Myapp.controller('LoginCtrl', ['$scope', '$state', 'LoginSrvs', function ($scope, $state, LoginSrvs)
{
$scope.login = function (LoginAccount) {
debugger;
var username = LoginAccount.username;
var password = LoginAccount.password;
var parameter = JSON.stringify({ username: username, password: password });
var loginData = LoginSrvs.login(parameter);
loginData.then(function (str) {
})
$state.go('index');
};
}]);
and my route .js
MyApp.config(
['$stateProvider',
'$urlRouterProvider',
function ($stateProvider,
$urlRouterProvider) {
debugger;
$stateProvider
.state('index', {
url: '/index',
templateUrl: ''
})
$urlRouterProvider.otherwise('/');
}]);
state.go not found and not trigger the controller action on click.
if you don't want any content then replace templateUrl: '' with template: ''.

$http and $stateParams in resolve of $stateProvider, Unknown provider error

The goal here is to send an http request with the same parameter of the state parameter. This will then display the food types associated with the cuisine type that has been clicked. Is this even theoretically possible?
"Error: [$injector:unpr] Unknown provider: getFoodsProvider <- getFoods <- AppCtrl"
js
var myApp = angular.module('myApp', ['ui.router']);
myApp.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url:'/',
templateUrl: 'partials/home.html',
controller: 'AppCtrl'
})
.state('food', {
url: '/food/:cuisine',
templateUrl: 'partials/food.html',
controller: 'AppCtrl',
resolve: {
getFoods: ['$http', '$stateParams', function($http, $stateParams) {
var url = '/getfoods/' + $stateParams.cuisine;
return $http.get(url).success(function(response) {
return response.data;
})
}]
}
});
$urlRouterProvider.otherwise('/');
});
myApp.controller('AppCtrl', ['$scope', 'getFoods', function ($scope, getFoods) {
$scope.foods= getFoods;
}]);
home
<md-list>
<md-list-item ng-repeat="cuisine in cuisines">
<a ui-sref="food({cuisine:cuisine})">{{cuisine}}</a>
</md-list-item>
</md-list>
food
<md-list>
<md-list-item ng-repeat="food in foods">
<div>{{food}}</div>
</md-list-item>
</md-list>
Your logic seems perfect and it should work. But I think as you're sending ajax request in the resolve and it works asynchronously you need a resolve there. And no need to use the resolve value in controller. Just set the data of the http response in a factory and use the same factory to get the data in the controller.
So try this:
resolve: {
getFoods: ['$http', '$stateParams','$q','foodData' function($http, $stateParams, $q,foodData) {
var url = '/getfoods/' + $stateParams.cuisine,
deferred = $q.defer(),
$http.get(url).success(function(response) {
foodData.setData(response.data);
deferred.resolve();
}).error(function(error){
deferred.reject();
$state.go(some other state);
})
return deferred.promise;
}]
}
On the off-chance that someone needs a solution to the same problem, you should know it was resolved by creating a separate controller for the state with the service (see comment below). The main controller was trying to load the 'getFoods' service when its associated state hadn't been activated yet. No promises necessary. Also, I added .data after the service in the controller.
new controller
var myApp= angular.module('myApp');
myApp.controller('foodCtrl', ['$scope', 'getFoods', function ($scope, getFoods) {
$scope.foods = getFoods.data; //added .data after service
}]);
main js
var myApp = angular.module('myApp', ['ui.router']);
myApp.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url:'/',
templateUrl: 'partials/home.html',
controller: 'AppCtrl'
})
.state('food', {
url: '/food/:cuisine',
templateUrl: 'partials/food.html',
controller: 'foodCtrl', //specify different controller
resolve: {
getFoods: ['$http', '$stateParams', function($http, $stateParams) {
var url = '/getfoods/' + $stateParams.cuisine;
return $http.get(url).success(function(response) {
return response.data;
})
}]
}
});
$urlRouterProvider.otherwise('/');
});

AngularJS trouble with UI-Router and linking id from one controller to another

I originally had my app set up with ng-route and I'm now switching over to ui-route. I used to use "when('/json/galleries/:projectId')" to generate a gallery when a thumbnail was clicked. Now with "state" I can't seem how to pass my projectId to the gallery state to generate my gallery.
App Module
(function() {
'use strict';
var bhamDesignsApp = angular.module('bhamDesignsApp', ['ngAnimate', 'ngTouch', 'ngSanitize', 'ngMessages', 'ngAria', 'ui.router', 'mm.foundation', 'appControllers']);
bhamDesignsApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'partials/home.html',
controller: 'ProjectsController'
})
.state('gallery', {
url: '/gallery/:projectId',
templateUrl: 'partials/gallery.html',
controller: 'GalleryController'
});
});
})();
App Controller
(function() {
'use strict';
var appControllers = angular.module('appControllers', []);
appControllers.controller('ProjectsController', ['$scope', '$http',
function ($scope, $http) {
$http.get('app/json/projects.json').success(function(data){
$scope.projects = data;
});
$scope.orderProp = '-year';
}]);
appControllers.controller('GalleryController', ['$scope', '$stateParams', '$http',
function($scope, $stateParams, $http) {
$http.get('app/json/galleries/' + $stateParams.projectId + '.json').success(function(data) {
$scope.gallery = data;
});
}]);
})();
HTML
.row
.small-12.medium-3.columns(ng-repeat="project in projects | orderBy:orderProp | filter:categoryFilter")
.tmbnail-container
a(ui-sref="gallery")
img.tmbnail(ng-src="{{project.thumbnail}}")
.text
h5 {{project.title}}
h6 {{project.year}}
.small-12.medium-6.columns
a(ui-sref="gallery")
You don't pass any ID to the state.
Change it to
a(ui-sref="gallery({projectId: project.id})"
(assuming project has an id field that holds its ID)
Documentation that explains how to use ui-sref: http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.directive:ui-sref

Using resolve in ui-router to authenticate a user

I'm having a issue in my Angular app with regards to the resolve section of the ui-router. I'm trying to present a login modal the first time a user hits the website.
In my app.config.js, how do I inject my 'loginService':
angular
.module('rage')
.config(config);
function config($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/dashboard");
$stateProvider
.state('main', {
url: "/dashboard",
templateUrl: "app/views/dashboard.html",
controller: 'MainCtrl',
data: { pageTitle: 'RAGE', requireLogin: true },
resolve: {
// *** WHERE DO I INJECT 'loginService' ? ***
authUser: function () {
return loginService.loginModal().then(function (user) {
$rootScope.userID = user.userId;
userService.openUserSession(razorEnvJson).then(function (data) {
// assign some scope vars here..
});
})
}
}
})
.state('login', {
url: "/login",
templateUrl: "app/views/login-view.html",
controller: 'LoginCtrl'
})
}
loginService code:
(function () {
'use strict';
angular.module('rage').service('loginService',
['$rootScope', '$modal', 'datacontext', 'userService', login]);
function login($rootScope, $modal, datacontext, userService) {
var modalInstance = null
this.loginModal = function(){
modalInstance = $modal.open({
animation: true,
templateUrl: 'app/components/login/login.html',
controller: 'LoginCtrl as login',
});
return modalInstance.result.then(function (user) {
return user;
});
};
}
})();
LoginCtrl controller code:
(function () {
'use strict';
angular.module('rage').controller('LoginCtrl',
['$rootScope', '$scope', '$modalInstance', '$q', 'datacontext', 'userService', authenticate]);
function authenticate($rootScope, $scope, $modalInstance, $q, datacontext, userService) {
var login = this;
// OK,CANCEL CLICK EVENTS FROM MODAL !!!
$scope.ok = function () {
// var user = userService.authenticateWebUser(); // **** TBD ****
var user = {userId: login.userId, pswd: login.pswd};
$modalInstance.close(user);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}
})();
I've also attempted $rootScope.$on('$stateChangeStart' event inside app.js to transition the state from main to login, but that hangs up on me.
**** MY UPDATED APP.CONFIG.JS CODE, SEPT 18 ****
Here is the proper usage of resolve: using ui-router states.
function config($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/dashboard");
$stateProvider
.state('main', {
url: "/dashboard",
templateUrl: "app/views/dashboard.html",
controller: 'MainCtrl',
data: { pageTitle: 'RAGE', requireLogin: true },
resolve: {
authUser: ['$rootScope', 'loginService', 'userService', function ($rootScope, loginService, userService) {
return loginService.loginModal().then(function (user) {
$rootScope.userID = user.userId;
initSession(user, $rootScope, loginService, userService);
})
}]
}
})
.state('login', {
url: "/login",
templateUrl: "app/views/login-view.html",
controller: 'LoginCtrl'
})
}
function initSession(user, $rootScope, loginService, userService) {
userService.getInitParams().then(function (envJson) {
// some code omitted here...
userService.openUserSession(envJson).then(function (data) {
var sessionID = data.data[0];
$rootScope.rageSessionVars.sessionID = sessionID;
$rootScope.rageSessionVars.userID = $rootScope.userID; // *** HOW TO SUSPEND ALL CODE UNTIL userID IS ASSIGNED ??? ***
console.log("sessionID = " + sessionID);
$rootScope.rageSessionVars.currDashboardName = "Default";
});
});
}
* MainCtrl controller code *
(function () {
'use strict';
angular.module('rage')
.controller('MainCtrl',
['$rootScope', '$scope', '$interval', '$window', '$state', '$location', 'widgetDefinitions',
'defaultWidgets', 'gadgetInitService', main]);
function main($rootScope, $scope, $interval, $window, $state, $location, widgetDefinitions, defaultWidgets, gadgetInitService, authUser) {
var main = this;
**** authUser IS NEVER DEFINED !!!
if ($scope.userID == undefined) { /// *** NOTHING WORKS HERE !!! ***
//$state.go('login');
//$location.url('index.html#/?login');
//return ;
}
if ($scope.userID == undefined) {
main.userName = "risk user";
}
else {
$scope.main.userName = $scope.userID;
}
}
})();
Edit:
I see your getting confused on the use of 'Resolve'.
It should be used when you want some data passed into the controller when it's being run. Not to run a function before initiating a controller.
This isn't what you really want in this situation.
It kinda depends on your authentication method, cookies/tokens etc.
Here is a similar method that I would follow.
Have a Login service which handles the following
-- Login/Logout of the user
-- Checks if the user is authenticated
In your Controller call your service to check if the user is logged in.
-- If the user is not logged in, then prompt login screen
-- If the user is logged in, then let the controller continue execution
How I handle it, is whenever the user makes an UnAuthorised request where the server returns a 401 response I call my LoginService to prompt the login screen again.
I use an authInterceptor in Angular to catch any 401 response from the server.
Here is a nice guide on it: http://onehungrymind.com/winning-http-interceptors-angularjs/
This allows you to write your Unauthorized handler in one place.
Hope that makes it a bit clearer.

How do I add a controller to a module in Angular JS

I have the following in my app.js:
var app = angular.module('app', ['admin', 'ui.compat', 'ngResource', 'LocalStorageModule']);
app.config(['$stateProvider', '$locationProvider',
function ($stateProvider, $locationProvider) {
$locationProvider.html5Mode(true);
var home = {
name: 'home',
url: '/home',
views: {
'nav-sub': {
templateUrl: '/Content/app/home/partials/nav-sub.html',
}
}
};
$stateProvider.state(home)
}])
.run(['$rootScope', '$state', '$stateParams', function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$state.transitionTo('home');
}]);
in admin.js:
angular
.module('admin', ['ui.state'])
.config(['$stateProvider', '$locationProvider',
function ($stateProvider, $locationProvider) {
$locationProvider.html5Mode(true);
var admin = {
name: 'admin',
url: '/admin',
views: {
'nav-sub': {
templateUrl: '/Content/app/admin/partials/nav-sub.html',
}
}
};
var adminContent = {
name: 'admin.content',
parent: admin,
url: '/content', views: {
'grid#': {
templateUrl: '/Content/app/admin/partials/content.html',
controller: 'AdminContentController'
}
}
}
$stateProvider.state(admin).state(adminContent)
}])
I am confused about how to wire up my AdminContentController. Currently I have the following:
app.controller('AdminContentController',
['$scope', 'entityService', 'gridService', 'gridSelectService', 'localStorageService',
function ($scope, entityService, gridService, gridSelectService, localStorageService) {
$scope.entityType = 'Content';
Can someone verify if this is the correct way for me to set up my module and add it to app. Should I be adding the controller to the app:
app.controller('AdminContentController',
or should this belong to the module 'admin'. If it should then how should I wire it up?
Based on what you have shared, the the controller should be created on admin module such as
var adminModule=angular.module('admin'); // This syntax get the module
adminModule.controller('AdminContentController',
['$scope', 'entityService', 'gridService', 'gridSelectService', 'localStorageService',
function ($scope, entityService, gridService, gridSelectService, localStorageService) {
$scope.entityType = 'Content';
You could also define the controller in continuation of your admin module declaration.
Yes that would work angular.module('admin') works as a getter. So you'll get the same module in each file.

Resources