AngularJS passing data between controllers - angularjs

I have spent hours trying to figure out how to pass data between controllers. Can someone please help me out?
This is the entirety if my angularjs file:
var app = angular.module('FitnessApp', []);
var HTTP_RESPONSE = function(response) { return response.data || response; };
var HTTP_ERROR = function(err) {return err; };
app.service('Share', ['$rootScope', '$timeout', function($rootScope, $timeout) {
var user = null;
var viewUser = null;
return {
setUser: function(newUser) {user = newUser; return $rootScope.$broadcast('user:updated'); },
getUser: function() {return user;},
setSearchedUser: function(searchedUser) {
viewUser = searchedUser; console.log(viewUser);
$timeout(function(){
return $rootScope.$broadcast('user:searched');
}, 5000);
//return $rootScope.$broadcast('user:searched');
},
getSearchedUser: function() {return viewUser;}
};
}]);
app.service('UserFactory', ['$http', function($http){
return {
// checkUserExists: function(user) {
// return $http.get('/user/exists', user).then(HTTP_RESPONSE, HTTP_ERROR);
// },
/*updateRating: function(id, rating) {
return $http.put('/user/updateRating', {_id: id, rating: rating}).then(HTTP_RESPONSE, HTTP_ERROR);
},*/
userLogIn: function(user) {
return $http.post('/user/login', user).then(HTTP_RESPONSE, HTTP_ERROR);
},
getUser: function(user_id) {
return $http.get('/user/userProfile/' + user_id).then(HTTP_RESPONSE, HTTP_ERROR);
},
userSignup: function(user) {
return $http.post('/user/adduser', user).then(HTTP_RESPONSE, HTTP_ERROR);
},
userEdit: function(user) {
return $http.put('/user/updateUser', user).then(HTTP_RESPONSE, HTTP_ERROR);
},
userChangeEmail: function(user) {
return $http.put('/user/changeEmail', user).then(HTTP_RESPONSE, HTTP_ERROR);
},
userChangePassword: function(user) {
return $http.put('/user/changePassword', user).then(HTTP_RESPONSE, HTTP_ERROR);
},
userDelete: function(del) {
return $http.put('/user/deleteUser/', del).then(HTTP_RESPONSE, HTTP_ERROR);
},
/*trainerLogin: function(trainer) {
return $http.post('/trainer/login', trainer).then(HTTP_RESPONSE, HTTP_ERROR);
},*/
trainerSignup: function(trainer) {
return $http.post('/trainer/addTrainer', trainer).then(HTTP_RESPONSE, HTTP_ERROR);
},
findUser: function(email) {
return $http.get('/user/findByEmail/' + email).then(HTTP_RESPONSE, HTTP_ERROR);
},
updateRating: function(idUser, idViewed, rating) {
return $http.put('/user/updateRating', {_id_user: idUser, _id_viewed: idViewed, rating: rating}).then(HTTP_RESPONSE, HTTP_ERROR);
},
getRating: function(idUser, idViewed) {
return $http.put('/user/getRating', {_id_user: idUser, _id_viewed: idViewed}).then(HTTP_RESPONSE, HTTP_ERROR);
}
};
}]);
// service that contains the ajax query
app.service('TrainerFactory', ['$http', function($http) {
return {
trainerAddEvent: function(trainerEvent) {
return $http.post('/trainer/addEvent', trainerEvent).then(HTTP_RESPONSE, HTTP_ERROR);
}
};
}]);
// controller which injects the above service
app.controller('EventController', ['$scope', 'TrainerFactory', 'Share', function($scope, TrainerFactory, Share) {
$scope.trainerAddEvent = function(newEvent) {
TrainerFactory.trainerAddEvent(newEvent).then(function(response) {
window.location.replace('/');
}, function(err) {}).finally(function() {});
};
}]);
app.controller('RootController', ['$scope', '$window', 'UserFactory', 'Share', function($scope, $window, UserFactory, Share) {
$scope.initUser = function(user_id) {
UserFactory.getUser(user_id).then(function(response) {
Share.setUser(response);
}, function(err) {
console.log(err);
}).finally(function(){});
};
$scope.$on('user:updated', function(data) {
$scope.user = Share.getUser();
});
$scope.findUser = function(email) {
UserFactory.findUser(email).then(function(response) {
switch(response.status) {
case 200:
Share.setSearchedUser(response.data);
// gets the user object from users.js '/user/findByEmail/:email'
// $scope.viewUser = response.data;
// $scope.showme = true;
// // gets the user's average rating
// $scope.userAverage = response.data.rating;
//********************************************************************* this will need to change when we go live
$window.location.href = "http://10.0.0.25:8001/user/profile/";
break;
case 404:
// User not found
$scope.login_err = 'Email not found, please try again';
break;
default:
$scope.login_err = 'An unexpected Error has occurred, please try again later.';
}
}, function(err) {
}).finally(function(){});
};
}]);
app.controller('ViewProfileController', ['$scope', 'UserFactory', 'Share', function($scope, SearchFactory, Share) {
$scope.viewUser = Share.getSearchedUser(); console.log($scope.viewUser);
// gets the current user
$scope.$on('user:updated', function(data) {
$scope.user = Share.getUser();
});
$scope.$on('user:searched', function(data) {console.log('here');
$scope.viewUser = Share.getSearchedUser(); console.log($scope.viewUser);
});
$scope.updateRating = function(idUser, idViewed, rating) {
UserFactory.updateRating(idUser, idViewed, rating).then(function(response) {
// update rating for front end
$scope.userAverage = response.data;
}, function(err) {
}).finally(function() {});
};
$scope.getRating = function(idUser, idViewed) {
UserFactory.getRating(idUser, idViewed).then(function(response) {
// relay the current user's rating of the user being viewed
console.log(response.data);
$scope.rating = response.data;
}, function(err) {
}).finally(function() {});
};
}]);
app.controller('SignupController', ['$scope', 'UserFactory', 'Share', function($scope, UserFactory, Share) {
$scope.sayHello = function() {
console.log('hello!');
};
$scope.$on('user:updated', function(data) {
$scope.user = Share.getUser();
});
$scope.clearMessages = function(messages) {
messages.forEach(function(message) {
message = null;
});
};
// Login
$scope.userLogin = function(user) {
UserFactory.userLogIn(user).then(function(response) {
switch(response.status) {
case 200:
// Okay to proceed
window.location.replace('/');
break;
case 406:
// Okay to proceed
window.location.replace('/newTrainer');
break;
case 404:
// User not found
$scope.login_err = 'Email not found, please try again';
break;
case 401:
// Password incorrect
$scope.login_err = 'Incorrect password, please try again';
break;
case 400:
// Invalid request
break;
default:
$scope.login_err = 'An unexpected Error has occurred, please try again later.';
}
}, function(err) {}).finally(function() {
});
};
// Signup
$scope.userSignup = function(user) {
UserFactory.userSignup(user).then(function(response) {
switch(response.status) {
case 200:
// Okay to proceed
window.location.replace('/');
break;
case 401:
// User already exists
$scope.signup_err = 'Email unavailable or invalid, please try again';
return;
case 400:
// Invalid Request
$scope.signup_err = 'An Error has occurred, please contact support#smb.com for help.';
break;
default:
$scope.signup_err = 'An unexpected Error has occurred, please try again later';
}
}, function(err) {}).finally(function() {});
};
$scope.trainerSignup = function(newTrainer) {
UserFactory.trainerSignup(newTrainer).then(function(response) {
switch(response.status) {
case 200:
// Okay to proceed
window.location.replace('/newTrainer');
break;
case 401:
// User already exists
$scope.signup_err = 'Email unavailable or invalid, please try again';
return;
case 400:
// Invalid Request
$scope.signup_err = 'An Error has occurred, please contact support#smb.com for help.';
break;
default:
$scope.signup_err = 'An unexpected Error has occurred, please try again later';
}
}, function(err) {}).finally(function() {});
};
}]);
app.controller('ProfileController', ['UserFactory', 'Share', '$scope', function(UserFactory, Share, $scope) {
$scope.$on('user:updated', function() {
$scope.user = Share.getUser();
});
/*$scope.updateRating = function(id, rating) {
return UserFactory.updateRating(id, rating).then(function(response) {
//$scope.user.rating.push(rating);
}, function(err) {
}).finally(function() {});
};*/
$scope.updateUser = function(updatedUser) {
return UserFactory.userEdit(updatedUser).then(function(response) {
$scope.message = 'Success!';
}, function(err) {
}).finally(function() {});
};
$scope.changeEmail = function(updatedUser) {
return UserFactory.userChangeEmail(updatedUser).then(function(response) {
}, function(err) {}).finally(function() {});
};
$scope.changePassword = function(updatedUser) {
return UserFactory.userChangePassword(updatedUser).then(function(response) {
}, function(err) {}).finally(function() {});
};
$scope.deleteUser = function(user) {
UserFactory.userDelete(user).then(function(response) {
switch(response.status) {
case 200:
window.location.replace('/user/signup');
break;
case 404:
$scope.del_err = 'Wrong Email, please try again';
break;
default:
$scope.del_err = 'An unexpected error occurred, please try again later';
}
}, function(err) {}).finally(function() {
console.error(err);
});
};
}]);
app.service('ActivityService', ['$http', function($http) {
return {
addActivity: function(activity) {
return $http.put('/user/addActivity', {activity: activity}).then(HTTP_RESPONSE, HTTP_ERROR);
},
removeActivity: function(activity) {
return $http.put('/user/removeActivity', {activity: activity}).then(HTTP_RESPONSE, HTTP_ERROR);
},
hasInterest: function(activity, array) {
var found = false;
array.forEach(function(interest) {
found = found || activity === interest;
});
return found;
}
};
}]);
app.controller('ActivityController', ['$scope', 'Share', 'ActivityService', function($scope, Share, ActivityService) {
$scope.$on('user:updated', function() {
$scope.user = Share.getUser();
});
$scope.addActivity = function(activity) {
return ActivityService.addActivity(activity).then(function(response) {
$scope.user.activities.push(activity);
}, function(err) {
}).finally(function() {});
};
$scope.removeActivity = function(activity) {
return ActivityService.removeActivity(activity).then(function(response) {
console.log(response);
$scope.user.activities = $scope.user.activities.filter(function(act) {
console.log(act, activity);
return activity !== act;
});
}, function(err) {
}).finally(function() {});
};
$scope.hasInterest = function(interest) {
return ActivityService.hasInterest(interest, $scope.user.activities);
};
}]);
app.service('MapService', function() {
return {
};
});
app.controller('MapController', ['$scope', 'Share', 'MapService', function($scope, Share, MapService) {
}]);
I am trying to pass information about the user object from the RootController to the ViewProfile Controller.
I think a problem I may be having is that switching the view may be destroying the variable?
Can someone please point me in the right direction?
Here is layout.jade which uses RootController:
doctype html
html
head
title= title
link(rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css')
link(rel='stylesheet', href='/stylesheets/style.css')
link(rel='stylesheet' type='text/css' href='/stylesheets/jquery.datetimepicker.css')
link(rel='stylesheet' type='text/css' href='/stylesheets/ratings.css')
block loadfirst
script(src="https://code.jquery.com/jquery-1.12.3.min.js"
integrity="sha256-aaODHAgvwQW1bFOGXMeX+pC4PZIPsvn2h1sArYOhgXQ=" crossorigin="anonymous")
script(src='https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js')
script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js')
script(src='/angular/fitnessapp.js')
body
div#wrapper(ng-app='FitnessApp')
div#header(ng-controller='RootController' ng-init='initUser(#{JSON.stringify(user)})')
nav.navbar.navbar-default
div.container-fluid
// Brand and toggle get grouped for better mobile display
div.navbar-header
button.navbar-toggle.collapsed(type='button', data-toggle='collapse', data-target='#bs-example-navbar-collapse-1', aria-expanded='false')
span.sr-only Toggle navigation
span.icon-bar
span.icon-bar
span.icon-bar
a.navbar-brand(href='/') SpotMeBro
// Collect the nav links, forms, and other content for toggling
div#bs-example-navbar-collapse-1.collapse.navbar-collapse
ul.nav.navbar-nav
li.dropdown
a.dropdown-toggle(href='#', data-toggle='dropdown', role='button', aria-haspopup='true', aria-expanded='false')
| Dropdown
span.caret
ul.dropdown-menu
li
a(href='#') {{user.type}}
li
a(href='#') Another action
li
a(href='#') Something else here
li.divider(role='separator')
li
a(href='#') Separated link
li.divider(role='separator')
li
a(href='#') One more separated link
form.navbar-form.navbar-left(role='search')
.form-group
input.form-control(type='text', placeholder='Search for an event')
button.btn.btn-default(type='submit') Submit
ul.nav.navbar-nav.navbar-right
if(!user)
li
a(href='/user/signup') Login/Signup
li
a(href='/trainer/signup') Trainer Signup
else
li
a(href='/user/search/') Search
li
a(ng-if='user.type' href='/trainer/createEvent') Create Event
li
a(href='/user/profile/') Profile
li
a(href='/user/interests') Interests
li
a(href='/user/settings') Settings
li
a(href='/logout') Logout
div
form.navbar-form.navbar-right(name='search' ng-submit="search.$valid && findUser(email);" novalidate)
div.form-group
div.input-group
input#email.form-control(name='email' ng-model='email' type='email' required)
button.btn.btn-default(type='submit') Search
div(ng-show='search.$submitted')
span.text-danger(ng-show='search.email.$error.required')
| Please enter an email.
span.text-danger(ng-show='search.email.$error.email')
| Please enter an email.
// /.navbar-collapse
// /.container-fluid
div#body
block content
div#footer
div.container-fluid.text-center
span.text-center Fütr
block scripts
And here is userProfile.jade which uses ViewProfileController:
extends layout
block content
div.container(ng-controller='ViewProfileController')
//- legend Search for user by email
//- form(name='search' ng-submit='search.$valid && findUser(email)' novalidate)
//- div.form-group
//- div.input-group
//- label(for='Email') Email
//- input#email.form-control(name='email' ng-model='email' type='email' required)
//- div(ng-show='search.$submitted || search.email.$touched')
//- span.text-danger(ng-show='search.email.$error.required')
//- | Please enter an email.
//- span.text-danger(ng-show='search.email.$error.email')
//- | Please enter an email.
//- div.form-group
//- button.btn.btn-primary(type='submit') Search
div
legend {{viewUser.firstName}} {{viewUser.lastName}}'s Profile {{user.email}} {{viewUser.email}}
div
span Email: {{viewUser.email}}
br
span Join Date: {{viewUser.joinDate}}
div
//img(src= "http://img.ifcdn.com/images/8c70c2b66b7a52154bb3d3faadf03995c2c1e5ca0144a8979c834e61a1e166f5_1.jpg" width="250" height="250")
img(src= "http://us.123rf.com/450wm/arcady31/arcady311212/arcady31121200002/16708573-anonymous-vector-sign.jpg" width="250" height="250")
div(ng-if='showme===true')
div(ng-init='getRating(user._id, viewUser._id)')
div#star-div {{viewUser.firstName}}'s average rating: {{userAverage}}
br
div(ng-if='user.email != viewUser.email')
span.star-rating
input(ng-change='updateRating(user._id, viewUser._id, rating);' ng-model='rating' type='radio', name='rate', value='1')
i
input(ng-change='updateRating(user._id, viewUser._id, rating);' ng-model='rating' type='radio', name='rate', value='2')
i
input(ng-change='updateRating(user._id, viewUser._id, rating);' ng-model='rating' type='radio', name='rate', value='3')
i
input(ng-change='updateRating(user._id, viewUser._id, rating);' ng-model='rating' type='radio', name='rate', value='4')
i
input(ng-change='updateRating(user._id, viewUser._id, rating);' ng-model='rating' type='radio', name='rate', value='5')
i
br
div Interests
br
label.label.label-default {{viewUser.activities}}
br
div Member Since
br
label.label.label-default {{viewUser.joinDate}}
br
div About Me
br
label.label.label-default {{viewUser.about}}
br
div RSVP'D Activities
br
label.label.label-default {{viewUser.upcomingActivities}}
br
div Past Activities
br
label.label.label-default {{viewUser.pastActivities}}
br

With your current navigation every time you navigate to a page the HTML sent back from the server will include everything from layout.jade.
Since this contains ng-app your application will restart and everything will be reset, including the variables in your service.
I recommend that you look into ngRoute instead for navigation.

Related

WebRTC remote video stream not working despite having src

I'm trying to make a simple AngularJS WebRTC video chat app based on this tutorial.
I'm able to connect to connect clients, add streams and play my own stream, but somehow I can't play the remote stream.
When I check the elements I can see that the videoplayer does in fact have a blob source, but it won't play it.
Can anyone tell me why it won't show?
HTML element:
Room controller:
angular.module('publicApp').controller('RoomCtrl', function ($sce, VideoStream, $location, $routeParams, $scope, Room)
{
if (!window.RTCPeerConnection || !navigator.getUserMedia) {
$scope.error = 'WebRTC is not supported by your browser. You can try the app with Chrome and Firefox.';
return;
}
var stream;
VideoStream.get()
.then(function (s) {
stream = s;
Room.init(stream);
stream = URL.createObjectURL(stream);
if (!$routeParams.roomId) {
Room.createRoom()
.then(function (roomId) {
$location.path('/room/' + roomId);
});
} else {
Room.joinRoom($routeParams.roomId);
}
}, function () {
$scope.error = 'No audio/video permissions. Please refresh your browser and allow the audio/video capturing.';
});
$scope.peers = [];
Room.on('peer.stream', function (peer) {
console.log('Client connected, adding new stream');
$scope.peers.push({
id: peer.id,
stream: URL.createObjectURL(peer.stream)
});
console.log($scope.peers);
});
Room.on('peer.disconnected', function (peer) {
console.log('Client disconnected, removing stream');
$scope.peers = $scope.peers.filter(function (p) {
return p.id !== peer.id;
});
});
$scope.getLocalVideo = function () {
return $sce.trustAsResourceUrl(stream);
};
});
Room factory:
angular.module('publicApp').factory('Room', function ($rootScope, $q, Io, config)
{
var iceConfig = { 'iceServers': [{ 'url': 'stun:stun.l.google.com:19302' }]},
peerConnections = {},
currentId, roomId,
stream;
function getPeerConnection(id)
{
if (peerConnections[id]) {
return peerConnections[id];
}
var pc = new RTCPeerConnection(iceConfig);
peerConnections[id] = pc;
pc.addStream(stream);
pc.onicecandidate = function (evnt) {
socket.emit('msg', { by: currentId, to: id, ice: evnt.candidate, type: 'ice' });
};
pc.onaddstream = function (evnt) {
console.log('Received new stream');
api.trigger('peer.stream', [{
id: id,
stream: evnt.stream
}]);
if (!$rootScope.$$digest) {
$rootScope.$apply();
}
};
return pc;
}
function makeOffer(id)
{
var pc = getPeerConnection(id);
pc.createOffer(function (sdp) {
pc.setLocalDescription(sdp);
console.log('Creating an offer for', id);
socket.emit('msg', { by: currentId, to: id, sdp: sdp, type: 'sdp-offer' });
}, function (e) {
console.log(e);
},
{ mandatory: { OfferToReceiveVideo: true, OfferToReceiveAudio: true }});
}
function handleMessage(data)
{
var pc = getPeerConnection(data.by);
switch (data.type) {
case 'sdp-offer':
pc.setRemoteDescription(new RTCSessionDescription(data.sdp), function () {
console.log('Setting remote description by offer');
pc.createAnswer(function (sdp) {
pc.setLocalDescription(sdp);
socket.emit('msg', { by: currentId, to: data.by, sdp: sdp, type: 'sdp-answer' });
});
});
break;
case 'sdp-answer':
pc.setRemoteDescription(new RTCSessionDescription(data.sdp), function () {
console.log('Setting remote description by answer');
}, function (e) {
console.error(e);
});
break;
case 'ice':
if (data.ice) {
console.log('Adding ice candidates');
pc.addIceCandidate(new RTCIceCandidate(data.ice));
}
break;
}
}
var socket = Io.connect(config.SIGNALIG_SERVER_URL),
connected = false;
function addHandlers(socket)
{
socket.on('peer.connected', function (params) {
makeOffer(params.id);
});
socket.on('peer.disconnected', function (data) {
api.trigger('peer.disconnected', [data]);
if (!$rootScope.$$digest) {
$rootScope.$apply();
}
});
socket.on('msg', function (data) {
handleMessage(data);
});
}
var api = {
joinRoom: function (r) {
if (!connected) {
socket.emit('init', { room: r }, function (roomid, id) {
currentId = id;
roomId = roomid;
});
connected = true;
}
},
createRoom: function () {
var d = $q.defer();
socket.emit('init', null, function (roomid, id) {
d.resolve(roomid);
roomId = roomid;
currentId = id;
connected = true;
});
return d.promise;
},
init: function (s) {
stream = s;
}
};
EventEmitter.call(api);
Object.setPrototypeOf(api, EventEmitter.prototype);
addHandlers(socket);
return api;
});
Directive:
angular.module('publicApp').directive('videoPlayer', function ($sce) {
return {
template: '<div><video ng-src="{{trustSrc()}}" autoplay></video></div>',
restrict: 'E',
replace: true,
scope: {
vidSrc: '#'
},
link: function (scope) {
console.log('Initializing video-player');
scope.trustSrc = function () {
if (!scope.vidSrc) {
console.log('No vidSrc found');
return undefined;
}
return $sce.trustAsResourceUrl(scope.vidSrc);
};
}
};
});
Room.html:
<div class="video-wrapper">
<video-player class="col-md-4" ng-repeat="peer in peers" vid-src="{{peer.stream}}"></video-player>
</div>
<div class="video-wrapper">
<div class="col-md-2">
<video ng-src="{{getLocalVideo()}}" autoplay muted></video>
</div>
</div>

How do I unit test further .then and .catch branching in an Angular controller?

(function() {
'use strict';
angular
.module('walletInformation')
.controller('WalletInformationController', WalletInformationController);
/* #ngInject */
function WalletInformationController(
$q,
$scope,
config,
logger,
session,
$interpolate,
flowstack,
profileService,
walletInformationFormlyService,
postMsg
) {
// jshint validthis: true
var vm = this;
var app = $scope.app;
var user = session.get('profile').profile || {};
vm.saveWalletInformation = saveWalletInformation;
vm.onClickCancel = onClickCancel;
vm.deleteWallet = deleteWallet;
vm.model = {
walletInformation : {
firstName: user.name.first,
lastName: user.name.last,
emailAddress: user.emailAddress,
phoneNumber: user.mobilePhone.phoneNumber,
keepMeUpdated: user.preferences.receiveEmailNotification
}
};
activate();
////////////////
/**
* #function activate
* #description init function for the controller
* Calls paymentCard to get the
* */
function activate() {
createFormFields();
logger.info('Activated the Wallet Information View.');
}
function createFormFields() {
vm.fields = walletInformationFormlyService.getFormlyFields($scope.app.text);
}
function saveWalletInformation() {
var updatedProfile = createLegacyProfileInformation();
profileService.updateProfileInformation(updatedProfile).then(onSuccess).catch(onError);
function onSuccess(response) {
session.set('profile', {
profile: response.profile
});
if (vm.model.walletInformation.currentPassword && vm.model.walletInformation.newPassword) {
changePasswordRequest();
} else {
flowstack.add('accountManagement');
flowstack.next();
}
}
function onError(error) {
logger.error('Verify save Wallet Information Error: ', error);
}
//changePassword
function changePasswordRequest() {
var updatedPassword = {
data: {
currentPassword: vm.model.walletInformation.currentPassword,
newPassword: vm.model.walletInformation.newPassword
}
};
profileService
.changePassword(updatedPassword)
.then(onChangePasswordSuccess, onChangePasswordError);
function onChangePasswordSuccess(response) {
flowstack.add('accountManagement');
flowstack.next();
logger.info('Change password request: ', response);
}
function onChangePasswordError(response) {
logger.error('Change Password Error: ', response);
}
}
}
function deleteWallet() {
var appText = app.text.walletInformation;
console.log(appText);
flowstack.add('confirmation');
flowstack.next({
data: {
title: appText.deleteWalletConfirmationTitle,
body: appText.deleteWalletConfirmationBody,
cancelButton: appText.deleteWalletConfirmationCancelButton,
confirmButton: appText.deleteWalletConfirmationConfirmButton,
onConfirm: function() {
profileService.deleteWallet().then(deleteProfileSuccess, deleteProfileFailure);
function deleteProfileSuccess(response) {
if (response.profile) {
logger.info('profile is successfully deleted.', response);
postMsg.send('closeSwitch');
}
}
function deleteProfileFailure(error) {
logger.error('something went wrong while deleting profile.', error);
}
},
onCancel: function() {
flowstack.add('walletInformation');
flowstack.next();
}
}
});
}
function createLegacyProfileInformation() {
var updatedProfile = user;
var formlyField = vm.model.walletInformation;
//Update the profile
updatedProfile.name = {
first: formlyField.firstName,
last: formlyField.lastName
};
updatedProfile.mobilePhone.phoneNumber = formlyField.phoneNumber;
updatedProfile.preferences.receiveEmailNotification = formlyField.keepMeUpdated;
return {
data: updatedProfile
};
}
function onClickCancel() {
flowstack.back();
}
}
})();
Coverage is saying that onSuccess of saveWalletInformation and changePasswordRequest isnt't covered but I'm not sure exactly how to test it, the only thing I've tested now is that the saveWalletInformation function is calling the profile service:
describe.only('WalletInformationController ---', function() {
var controller, scope;
var userProfile = {
profile: {
name: {
first: 'someonefirstname',
last: 'someoneslastname'
},
emailAddress: 'someone#something.com',
mobilePhone: {
countryCode: 'US+1',
phoneNumber: '123 212 2342'
},
preferences: {
receiveEmailNotification: true
}
}
};
beforeEach(function() {
bard.appModule('walletInformation');
bard.inject(
'$q',
'$controller',
'$rootScope',
'api',
'flowstack',
'logger',
'session',
'profileService'
);
session.set('profile', userProfile);
});
beforeEach(function() {
sandbox = sinon.sandbox.create();
scope = $rootScope.$new();
scope.app = {
text: {
global: {},
walletInformation: {
deleteWalletConfirmationTitle: 'Confirm Wallet Deletion?'
},
userInformation: {
emailValidation: 'Please enter valid email'
},
signin: {
rememberMeLabel: 'remember me'
}
}
};
controller = $controller('WalletInformationController', {
$scope: scope
});
loggerErrorStub = sandbox.stub(logger, 'error');
sandbox.stub(logger, 'info');
controller = $controller('WalletInformationController', {
$scope: scope
});
});
describe('saveWalletInformation method', function() {
beforeEach(function() {
// apiStub.restore();
sandbox.stub(profileService, 'updateProfileInformation', function() {
return $q.when(userProfile);
});
});
it('should saveWalletInformation successfully', function() {
controller.saveWalletInformation();
expect(profileService.updateProfileInformation).to.have.been.called;
});
it('should log error msg when saveWalletInformation call fails', function() {
profileService.updateProfileInformation.restore();
sandbox.stub(profileService, 'updateProfileInformation', function() {
return $q.reject();
});
controller.saveWalletInformation();
scope.$apply();
expect(loggerErrorStub).to.have.been.calledOnce;
});
it('should call changePasswordRequest when currentPassword and newPassword are set', function() {
sandbox.stub(profileService, 'changePassword', function() {
return $q.when({
success: true,
extensionPoint: null
});
});
sandbox.stub(flowstack, 'add');
sandbox.stub(flowstack, 'next');
controller.saveWalletInformation();
// scope.$apply();
// expect(flowstack.next).to.have.been.calledOnce;
// expect(flowstack.add).to.have.been.calledOnce;
expect(profileService.updateProfileInformation).to.have.been.called;
// expect(profileService.changePassword).to.have.been.called;
});
});
You can let the service call go a step further and instead of verifying that service function was called, as you do here:
expect(profileService.updateProfileInformation).to.have.been.called;
You can instead mock the response from the api call with $httpBackend:
httpBackend.expectGET('your/url/here').respond(200, {response object...});
or
httpBackend.expectGET('your/url/here').respond(500, {error object...});
Then you'll be hitting both the error and success functions when your tests run

Implementing similar functions in a function with (Input) Parameters?

I have the following function to launch Skype from my Ionic app:
myApp.controller("launchSkypeCtrl", function($scope, $ionicPopup, $cordovaInAppBrowser) {
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
$scope.launchSkype = function launchSkype() {
var scheme;
if (device.platform === 'iOS') {
scheme = 'skype://';
} else if (device.platform === 'Android') {
scheme = 'com.skype.raider';
} else if (device.platform === 'wp') {
scheme = 'skype:';
} else if (device.platform === 'windows8') {
scheme = 'skype:';
}
navigator.startApp.check(scheme, function(message) { /* success */
navigator.startApp.start(scheme, function(message) {
}, function(error) { /* error */
$ionicPopup.alert({
title: "Skype not startet!",
content: "Skype not startet!"
})
});
}, function(error) {
$ionicPopup.alert({
title: "Skype not installed",
content: "Skype not installed on this device. Please install it!"
})
});
}
}
});
I also have the similar function, which starts Google Hangouts:
myApp.controller("launchHangoutsCtrl", function($scope, $ionicPopup, $cordovaInAppBrowser) {
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
$scope.launchHangouts = function launchSkype() {
var scheme;
if (device.platform === 'iOS') {
scheme = 'gtalk://';
} else if (device.platform === 'Android') {
scheme = 'com.google.android.talk';
} else if (device.platform === 'wp') {
scheme = 'gtalk:';
} else if (device.platform === 'windows8') {
scheme = 'gtalk:';
}
navigator.startApp.check(scheme, function(message) { /* success */
navigator.startApp.start(scheme, function(message) {
}, function(error) { /* error */
$ionicPopup.alert({
title: "Google Hangouts not started!",
content: "Google Hangouts not started!"
})
});
}, function(error) {
$ionicPopup.alert({
title: "Google Hangouts not installed!",
content: "Google Hangouts not installed! Please install it!"
})
});
}
}
});
As can be seen, only the links of Apps are different. Otherwise everything is the same. Errors are of course linked with the app name. My question is how can I put these two same functions with different app links in a function? I have more then two functions. I will thus avoid the repetition of the same functions. How can I output the error messages of the respective apps in a single function? How would the function which includes the above features look like? How would the call of the start of the respective app look like?
You can pass the corresponding strings as a parameter. In this case an object:
function launchApp($ionicPopup, appConfig) {
var scheme;
if (device.platform === 'iOS') {
scheme = appConfig.iosScheme;
} else if (device.platform === 'Android') {
scheme = appConfig.androidScheme;
} else if (device.platform === 'wp') {
scheme = appConfig.wpScheme;
} else if (device.platform === 'windows8') {
scheme = appConfig.windows8Scheme;
}
navigator.startApp.check(scheme, function(message) { /* success */
navigator.startApp.start(scheme, function(message) {
}, function(error) { /* error */
$ionicPopup.alert({
title: appConfig.appName + " not started!",
content: appConfig.appName + " not started!"
})
});
}, function(error) {
$ionicPopup.alert({
title: appConfig.appName + " not installed!",
content: appConfig.appName + " not installed! Please install it!"
})
});
}
myApp.controller("launchSkypeCtrl", function($scope, $ionicPopup, $cordovaInAppBrowser) {
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
var skypeConfig = {
"appName": "Skype",
"iosScheme": "skype://",
"androidScheme": "com.skype.raider",
"wpScheme": "skype:",
"windows8Scheme": "skype:"
}
$scope.launchSkype = launchApp($ionicPopup, skypeConfig);
}
});
myApp.controller("launchHangoutsCtrl", function($scope, $ionicPopup, $cordovaInAppBrowser) {
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
var hangoutConfig = {
"appName": "Google Hangouts",
"iosScheme": "gtalk://",
"androidScheme": "com.google.android.talk:",
"wpScheme": "gtalk:",
"windows8Scheme": "gtalk:"
}
$scope.launchHangouts = launchApp($ionicPopup, hangoutConfig);
}
});
Where you define the objects is up to you.
Edit:
To get $scope.launchSykpe and $scope.launchHangouts to be functions instead of calls, use the below launchApp function:
function launchApp($ionicPopup, appConfig) {
return function() {
var scheme;
if (device.platform === 'iOS') {
scheme = appConfig.iosScheme;
} else if (device.platform === 'Android') {
scheme = appConfig.androidScheme;
} else if (device.platform === 'wp') {
scheme = appConfig.wpScheme;
} else if (device.platform === 'windows8') {
scheme = appConfig.windows8Scheme;
}
navigator.startApp.check(scheme, function(message) { /* success */
navigator.startApp.start(scheme, function(message) {
}, function(error) { /* error */
$ionicPopup.alert({
title: appConfig.appName + " not started!",
content: appConfig.appName + " not started!"
})
});
}, function(error) {
$ionicPopup.alert({
title: appConfig.appName + " not installed!",
content: appConfig.appName + " not installed! Please install it!"
})
});
};
}
I didn't test it, but it should work now as inteded.

How can I use geolocation watchPosition in angularjs?

i want to use the geolocation.watchPosition in angular js in order to find my new location every 3minutes something like gps tracker. Can anyone help me please?
appControllers.controller('Ctrl', ['$scope','$routeParams', '$http','$window','$interval',
function geo_success(position) {
var lat = position.coords.latitude;
var lng = position.coords.longitude;
console.log(lat);
console.log(lng);
$scope.$apply(function(){
$scope.lat = lat;
$scope.lng = lng;
});
$scope.latlng = function(){
$http.post('/profile', {
latitude: $scope.lat,
longitude: $scope.lng
})
.success(function(user){
// No error: authentication OK
$rootScope.message = 'Lat/Lng send ok!';
})
.error(function(){
// Error: authentication failed
$rootScope.message = 'Lat/Lng dont send';
});
};
}
function geo_error(error){
console.log ("gps lost");
}
var watchID = $window.navigator.geolocation.watchPosition(geo_success,geo_error, {enableHighAccuracy: true });
}]);
this i have write
Hope this could help.
angular.module("GeoService",[]).
factory('GeoLocation',['$rootScope', '$window', '$q', '$resource', function($rootScope, $window, $q, $resource){
var _geoCapable = false,
_deferred = $q.defer(),
_errorMsg = null;
//Geolocation options
_option = {
enableHighAccuracy:true,
timeout: 5000,
maximumAge: 0,
desiredAccuracy: 0,
frequency: 1
};
if($window.navigator && $window.navigator.geolocation){
_geoCapable = true;
}
if(!_geoCapable){
$rootScope.$broadcast('geo:error', 'Geolocation not supported');
}
//Geolocation function onSucces
_onSucces = function (position) {
_deferred.resolve(position);
};
//Geolocation function onFail
_onFail = function (error) {
switch (error.code) {
case error.PERMISSION_DENIED:
_errorMsg = "User denied the request for Geolocation."
break;
case error.POSITION_UNAVAILABLE:
_errorMsg = "Location information is unavailable."
break;
case error.TIMEOUT:
_errorMsg = "The request to get user location timed out."
break;
case error.UNKNOWN_ERROR:
_errorMsg = "An unknown error occurred."
break;
};
$rootScope.$broadcast('geo:error', _errorMsg);
_deferred.reject(_errorMsg);
};
//Service API
var _locationService = {
//getPosition() function:
getLocation: function(){
if(!_geoCapable){
return _deferred.reject();
};
$window.navigator.geolocation.getCurrentPosition(_onSucces,_onFail,_option);
return _deferred.promise;
},
//watchPosition() function:
watchPosition: function(){
if(!_geoCapable){
$rootScope.$broadcast('geo:error','Geolocation not supported');
};
$window.navigator.geolocation.watchPosition(function(position){
$rootScope.$broadcast('geo:positionUpdate', position);
}, _onFail);
}
};
return _locationService;
}]);

angular, try to display object in ng-repeat fails

i'm writing an mobile application in javascript with angularJS and ionicframework (last beta v.11), i create dinamically an object and want to display all objects inside in a ng-repeat. Why nr-repeat don't display anything?
This is screen from my object:
I use this code for put values in scope:
$scope.distanceSuppliers = myCar;
And this is the code in html:
<ion-item ng-repeat="(id, supplier) in distanceSuppliers">
<div class="items item-button-right" ng-click="openDetails(id)">
{{supplier.name}}<br />
{{supplier.address}}<br />
</div>
</ion-item>
This is my complete code for JS:
.controller('suppliers', function($scope, cw_db, $ionicPopup, $ionicActionSheet, appdelegate, $rootScope, $firebase, $location, $ionicLoading, cw_position) {
$ionicLoading.show({
template: 'Updating data..'
});
var geocoder;
var tot = 0;
var done = 0;
geocoder = new google.maps.Geocoder();
cw_db.getData(cw_db.getSuppliers(), "", function(suppliers) {
cw_position.getPosition(function (error, position) {
suppliers.on('value', function(supp) {
$scope.distanceSuppliers = {};
tot = 0;
done = 0;
supp.forEach(function(childSnapshot) {
tot++;
var childData = childSnapshot.val();
if (childData.address) {
calculateDistance(childData, position.coords.latitude, position.coords.longitude);
}
});
});
$ionicLoading.hide();
});
});
function calculateDistance(childData, usrLat, usrLon) {
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [new google.maps.LatLng(usrLat, usrLon)],
destinations: [childData.address],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, function(response, status) {
if (status != google.maps.DistanceMatrixStatus.OK) {
alert('Error was: ' + status);
} else {
done++;
var results = response.rows[0].elements;
childData.distance = results[0].distance.value;
$scope.distanceSuppliers.push(childData);
if (done == tot) {
console.log($scope.distanceSuppliers);
}
}
});
}
$scope.openDetails = function(index) {
//appdelegate.setCallId(index);
//$location.path("/app/supplierDetails");
}
})
what's wrong?
Not sure, but I believe you have a data binding update problem.
Try using the $timeout to force the render:
w_position.getPosition(function (error, position) {
$timeout(function() {
suppliers.on('value', function(supp) {
$scope.distanceSuppliers = {};
tot = 0;
done = 0;
supp.forEach(function(childSnapshot) {
tot++;
var childData = childSnapshot.val();
if (childData.address) {
calculateDistance(childData, position.coords.latitude, position.coords.longitude);
}
});
});
$ionicLoading.hide();
});
});
And don't forget to add the $timeout parameter to the controller:
.controller('suppliers', function($scope, ...<other parameters here>..., $timeout) {
I found the problem! Fix using $scope.$apply();
The problem was that i was writing in a different $scope using this code:
cw_position.getPosition(function (error, position) {
suppliers.on('value', function(supp) {
tot = 0;
done = 0;
supp.forEach(function(childSnapshot) {
tot++;
var childData = childSnapshot.val();
if (childData.address) {
calculateDistance(childData, position.coords.latitude, position.coords.longitude);
}
});
});
$ionicLoading.hide();
});
where cw_position.getPosition call a js with this code:
angular.module('cw_position', [])
.service('cw_position', function() {
this.getPosition = function(callback) {
navigator.geolocation.getCurrentPosition(
function (position) {
return callback(null, position);
},
function(error) {
return callback(error, null);
}
);
}
// Built google maps map option
//
this.getGoogleMapOptions = function (lat, lon, zoom, type) {
if (type == null) {
type = google.maps.MapTypeId.ROADMAP;
}
var mapOptions = {
center: new google.maps.LatLng(lat, lon),
zoom: zoom,
mapTypeId: type
};
return mapOptions;
}
});
navigator.geolocation.getCurrentPosition causes the 'problem'
Thx to all for your help

Resources