How to call function of one controller from another controller AngularJs - angularjs

I have two controller name called like:
AutoLoginCtrl
LoginCtrl
my facebook logout function present in Login Controller, from AutoLogin controller how could I call logout function which is Login Controller.
I have tried like this by using $rootscope and $on
LoginCtrl.js
ionApp.controller('LoginCtrl', function($scope, $state, $ionicModal, $rootScope, $q, $timeout, UserService, $ionicLoading, $ionicActionSheet) {
$scope.showLogOutMenu = function() {
var hideSheet = $ionicActionSheet.show({
destructiveText: 'Logout',
titleText: 'Are you sure you want to logout? This app is awsome so I recommend you to stay.',
cancelText: 'Cancel',
cancel: function() {},
buttonClicked: function(index) {
return true;
},
destructiveButtonClicked: function() {
$ionicLoading.show({
template: 'Logging out...'
});
// Facebook logout
facebookConnectPlugin.logout(function() {
$ionicLoading.hide();
$state.go('login');
},
function(fail) {
$ionicLoading.hide();
});
}
});
};
$rootScope.$on("LogoutFunction", function(){
$scope.parentmethod();
});
})
AutoLoginCtrl
ionApp.controller('AutoLoginCtrl', function($scope, $state, $ionicModal, $rootScope, $q, $timeout, UserService, $ionicLoading, $ionicActionSheet) {
var checkPage = "home";
$scope.logout = function() {
$rootScope.$emit("LogoutFunction", {});
}
})

You decided to use $emit a.e. child controller notifies parent controller. Is it true? AutoLoginCtrl is a child of LoginCtrl or maybe you need to use $broadcast instead?
The second problem might be:
For some reason LoginCtrl still didn't load and no one listens on LogoutFunction event.
Please check these cases

you can make a Public Class (Provider Maybe) and make a function in it that call a function 'Logout()' from 'LoginController'
and call this provider function in Your 'AutoLogin' Controller

You can have the logout function in a factory and call it from both the controllers, like this.
Factory basic demo: here
Code:
ionApp.controller('LoginCtrl', function($scope, $ionicModal, $rootScope, $q, $timeout, UserService, SharedService) {
$scope.showLogOutMenu = function() {
SharedService.logout();
};
}).factory('SharedService', function ($ionicActionSheet, $ionicLoading, $state) {
return {
logout: function () {
var hideSheet = $ionicActionSheet.show({
destructiveText: 'Logout',
titleText: 'Are you sure you want to logout? This app is awsome so I recommend you to stay.',
cancelText: 'Cancel',
cancel: function() {},
buttonClicked: function(index) {
return true;
},
destructiveButtonClicked: function() {
$ionicLoading.show({
template: 'Logging out...'
});
// Facebook logout
facebookConnectPlugin.logout(function() {
$ionicLoading.hide();
$state.go('login');
},
function(fail) {
$ionicLoading.hide();
});
}
});
}
}
}).controller('AutoLoginCtrl', function($scope, $ionicModal, $rootScope, $q, $timeout, UserService, SharedService) {
var checkPage = "home";
$scope.logout = function() {
SharedService.logout();
}
});

Related

call a soap webservice from ionic

i'm trying to call a soap webservice using this method : http://mcgivery.com/soap-web-services-angular-ionic/ however my screen only shows a blank page instead of the login screen. what could be the probleim?
here's my services.js code:
.factory('loginService', ['$soap', function($soap){
var base_url = 'http://localhost/UserService3/WebService1.asmx';
return {
GetUser: function(uname){
return $soap.post(base_url,"getUserbyUsername", {Username: uname});
}
};
}])
and here's my controller.js code:
.controller('loginCtrl', ['$scope', '$stateParams', '$location', '$state', 'sharedProperties2','ConnectivityMonitor', '$ionicLoading', 'loginService',
function ($scope, $stateParams, $location, $state, sharedProperties2,
ConnectivityMonitor, $ionicLoading, loginService) {
$scope.show = function() {
$ionicLoading.show({
template: '<ion-spinner icon="android"></ion-spinner>',
showBackdrop: false
});
};
$scope.hide = function(){
$ionicLoading.hide();
};
$scope.userdata = {}
$scope.enterlogin = function(usern,pass)
{
userFactory.GetUser(usern).then(function(response) {
alert('get = ' + JSON.stringify(response.data));
})
}
}])
apparently it could not see the previous location of the added scripts angular.soap.js and soapclient.js, so i put the 2 files inside a folder named angular-soap inside the lib folder.

Angular-Jasmine injecting a service into the test

New to Jasmine, I am trying to instantiate my controller which has a list of dependencies (mainly the services I have written) and all the different ways I';ve tried haven't been right.
Here is my controller:
(function () {
'use strict';
angular.module('app.match')
.controller('MatchController', MatchController);
MatchController.$inject = ['APP_CONFIG', '$authUser', '$http', '$rootScope', '$state', '$stateParams', 'SearchService', 'ConfirmMatchService', 'MusicOpsService', 'ContentOpsService', 'MatchstickService', 'MatchService', 'Restangular'];
function MatchController(APP_CONFIG, $authUser, $http, $rootScope, $state, $stateParams, searchService, confirmMatchService, musicOpsService, contentOpsService, matchstickService, matchService, Restangular) {
var vm = this;
vm.greeting = '';
.
.
)();
Here is my test
(function(){
'use strict';
describe('app module', function() {
var MatchController;
//beforeEach(module('app.match'));
beforeEach(function($provide) {
module = angular.module('app.match');
$provide.service('SearchService', function(){
});
});
beforeEach(module('app.config'));
beforeEach(module('auth'));
beforeEach(inject(function($controller, APP_CONFIG, $authUser, $http, $rootScope, $state, $stateParams) {
MatchController = $controller('MatchController', {'APP_CONFIG':APP_CONFIG, '$authUser':$authUser, '$http':$http, '$rootScope':$rootScope, '$state':$state, '$stateParams':$stateParams, '$provide':$provide});
}));
describe("Match controller", function() {
it("should be created successfully", function() {
expect(MatchController).toBeDefined();
});
});
});
})();
Running test the above way gives me the following error:
TypeError: 'undefined' is not a function (evaluating '$provide.service('SearchService', function(){
})')
Try injecting the SearchService like this instead of using beforeEach.
describe('app module', function() {
var MatchController, SearchService;
beforeEach(module('app.match'));
beforeEach(module('app.config'));
beforeEach(module('auth'));
beforeEach(inject(function($controller, APP_CONFIG, $authUser, $http, $rootScope, $state, $stateParams, _SearchService_) {
SearchService = _SearchService_;
MatchController = $controller('MatchController', {
'APP_CONFIG':APP_CONFIG,
'$authUser':$authUser,
'$http':$http,
'$rootScope':$rootScope,
'$state':$state,
'$stateParams':$stateParams,
'$provide':$provide,
'SearchService': _SearchService_
});
}));
describe("Match controller", function() {
it("should be created successfully", function() {
expect(MatchController).toBeDefined();
});
});
});
})();
Similarly, you'll have to inject other services as well that your controller is relying on.

Getting started with Ionic/Angular unit testing controllers with jasmine

I have been trying to write unit tests for angular controller in Ionic framework with jasmine and karma. Here is my controller.
angular.module('starter').controller('LoginCtrl', ['$scope', 'AuthService', '$ionicPopup', '$state', function LoginCtrl($scope, AuthService, $ionicPopup, $state) {
$scope.user = {
name: '',
password: ''
};
$scope.login = function() {
AuthService.login($scope.user).then(function(msg) {
$state.go('inside');
}, function(errMsg) {
var alertPopup = $ionicPopup.alert({
title: 'Login failed!',
template: errMsg
});
});
};
}]);
angular.module('starter').controller('RegisterCtrl', ['$scope', 'AuthService', '$ionicPopup', '$state', function RegisterCtrl($scope, AuthService, $ionicPopup, $state) {
$scope.user = {
name: '',
password: ''
};
$scope.signup = function() {
AuthService.register($scope.user).then(function(msg) {
$state.go('outside.login');
var alertPopup = $ionicPopup.alert({
title: 'Register success!',
template: msg
});
}, function(errMsg) {
var alertPopup = $ionicPopup.alert({
title: 'Register failed!',
template: errMsg
});
});
};
}]);
angular.module('starter').controller('InsideCtrl', ['$scope', 'AuthService', 'API_ENDPOINT', '$http', '$state', function InsideCtrl($scope, AuthService, API_ENDPOINT, $http, $state) {
$scope.destroySession = function() {
AuthService.logout();
};
$scope.getInfo = function() {
$http.get(API_ENDPOINT.url + '/memberinfo').then(function(result) {
$scope.memberinfo = result.data.msg;
});
};
$scope.logout = function() {
AuthService.logout();
$state.go('outside.login');
};
}]);
angular.module('starter').controller('AppCtrl', ['$scope', '$state', '$ionicPopup', 'AuthService', 'AUTH_EVENTS', function AppCtrl($scope, $state, $ionicPopup, AuthService, AUTH_EVENTS) {
$scope.$on(AUTH_EVENTS.notAuthenticated, function(event) {
AuthService.logout();
$state.go('outside.login');
var alertPopup = $ionicPopup.alert({
title: 'Session Lost!',
template: 'Sorry, You have to login again.'
});
});
}]);
})(reader || (reader = {}));
I want to have this 3 test suits:
Should call login on $AuthService Service
If login successful, should change state to inside
If login unsuccessful, should show a popup error message
I em try to write som test but i thin that i am not injecting the controller properly. Here is the code for my tests:
describe('LoginCtrl', function() {
var $controller,
LoginCtrl,
controller,
deferredLogin,
$scope,
AuthServiceMock,
stateMock,
ionicPopupMock;
// load the module for our app
beforeEach(angular.mock.module('starter'));
// disable template caching
beforeEach(angular.mock.module(function($provide, $urlRouterProvider) {
$provide.value('$ionicTemplateCache', function(){} );
$urlRouterProvider.deferIntercept();
}));
// instantiate the controller and mocks for every test
beforeEach(angular.mock.inject(function(_$controller_, $q, $rootScope) {
deferredLogin = $q.authToken();
$scope = $rootScope.$new();
// mock dinnerService
AuthServiceMock = {
login: jasmine.createSpy('login spy')
.and.returnValue(deferredLogin.promise)
};
// mock $state
stateMock = jasmine.createSpyObj('$state spy', ['go']);
// mock $ionicPopup
ionicPopupMock = jasmine.createSpyObj('$ionicPopup spy', ['alert']);
// instantiate LoginController
$controller = _$controller_;
}));
describe('login function', function() {
// call doLogin on the controller for every test
beforeEach(inject(function(_$rootScope_) {
$rootScope = _$rootScope_;
var user = {
name: 'Boris',
password: 'Boris'
};
$scope.login(user);
}));
it('should call login on $AuthService Service', function() {
LoginCtrl = $controller('LoginCtrl', {
'$scope': $scope,
'$state': stateMock,
'$ionicPopup': ionicPopupMock,
'$AuthService': AuthServiceMock
});
console.log(LoginCtrl);
expect(LoginCtrl).toBeDefined();
});
describe('when the login is executed,', function() {
xit('if successful, should change state to inside', function() {
deferredLogin.resolve();
$rootScope.$digest();
expect(stateMock.go).toHaveBeenCalledWith('inside');
});
xit('if unsuccessful, should show a popup', function() {
deferredLogin.reject();
$rootScope.$digest();
expect(ionicPopupMock.alert).toHaveBeenCalled();
});
});
});
});
Here is my Karma file settings
files: [
'www/lib/ionic/js/ionic.bundle.js',
'www/js/*.js',
'www/lib/angular-mocks/angular-mocks.js',
'www/spec/*.js'
],

Parent view does not get updated

I am using angular with ngDialog. I have in my view a list of users with an edit button which opens the user details in a ngDialog. Now when i save the data in my ngDialog I would like the list of users to be updated.
I thought to use a observer pattern for this. However the handler doesn't fire.
Here is my code:
User Controller
angular.module('myApp')
.controller('UserController', function($scope, User){
//this method gets fired when the dialog is saved
$scope.update = function(user)
{
User.update(user);
$scope.$broadcast('refresh-users');
return true;
}
});
UsersController:
angular.module('myApp')
.controller('UsersController', function($scope, User, ngDialog){
var loadUsers = function(users) {
$scope.users = users;
}
var handleErrors = function(response) {
console.error(response)
}
$scope.userPopup = function(id)
{
ngDialog.open(
{
template:'../partials/user.html',
controller: 'UserController',
data: {'id': id},
scope: $scope
});
}
$scope.$on('refresh-users', function handler(){
console.log('handler');
User.getAll()
.then(loadUsers)
.catch(handleErrors);
});
});
How could I solve this?
Use $rootScope instead of $scope as these two controllers are not using the same scope.
As has already been mentioned you want to use $rootScope for broadcasting if what you're trying to communicate is on another scope.
User Controller
angular.module('myApp')
.controller('UserController', function($scope, $rootScope, User){
//this method gets fired when the dialog is saved
$scope.update = function(user)
{
User.update(user);
$rootScope.$broadcast('refresh-users');
return true;
}
});
UsersController:
angular.module('myApp')
.controller('UsersController', function($scope, $rootScope, User, ngDialog){
var loadUsers = function(users) {
$scope.users = users;
}
var handleErrors = function(response) {
console.error(response)
}
$scope.userPopup = function(id)
{
ngDialog.open(
{
template:'../partials/user.html',
controller: 'UserController',
data: {'id': id},
scope: $scope
});
}
$rootScope.$on('refresh-users', function handler(){
console.log('handler');
User.getAll()
.then(loadUsers)
.catch(handleErrors);
});
});

How can I test if a $cookie was set in an AngularJS service?

My service is:
myApp.service('userService', [
'$http', '$q', '$rootScope', '$state', '$cookies', '$base64', function($http, $q, $rootScope, $state, $cookies, $base64) {
var user;
user = {};
this.logout = function() {
user = {};
delete $cookies.userAccessKey;
return $state.transitionTo('login');
};
}
]);
I want to write a unit test to make sure that the $cookies.userAccessKey was deleted. How can I do this? While I'm at it, how can I ensure that user was set to empty?
To check if user is null, just add a public getter or checker :
myApp.service('userService', [
'$http', '$q', '$rootScope', '$state', '$cookies', '$base64', function($http, $q, $rootScope, $state, $cookies, $base64) {
var user;
this.user = {}; // or a method this.isLoggedIn() for more security
this.logout = function() {
this.user = {};
delete $cookies.userAccessKey;
return $state.transitionTo('login');
};
}
]);
Then, in your tests :
describe('logout', function(){
beforeEach(function(){
userService.login(); //relog before each test
});
it('should remove the userAccessKey from cookie', function() {
userService.logout();
inject(function($cookies) {
expect(cookies.userAccessKey).toBeUndefined();
});
});
it('should reset user object', function() {
userService.logout();
expect(userService.user).toEqual({});
});
});
});

Resources