I have been trying to work this out for a while now. I have been working on an ionic + parse login,register,forgot password app. That being said Ionic is the front end and parse.com as the database.
The functions work perfectly from local host in the web broswer when using Ionic serve from command line, but when I build the app for android (ionic build android) or emulate (ionic emulate android) or test it on on an android device I get a range of error messages:
When I attempt to login in; An unexpected error has occurred please try again
when I attempt to reset my password; An unexpected error has occurred please try again
When I attempt to register I am shown this error message:
XMLHttpRequest failed: {statusText":Not Found","status::404,"responseURL":https://api.parse.com/1/users","response":""resp onseType":""."responseXML":null,"responseText":"","upload":{loadend":null,"onload":null,"onprogress":null,"onloadstart":null,"onloadend":null,:onload":null,"onerror":null"onabort":null},"withCredentials":false,"readyState":4"timeout":0,"ontimeout":null,"onprogress":null,"onloadstart":null,:onloadend":null,"onload":null,"onerror":null,:onabort":null}
Here is my code:
Register page:template folder
<ion-view title="Register">
<ion-content has-header="true" has-tabs="true" padding="true">
<div class="list">
<label class="item item-input">
<input type="email" ng-model="user.email" placeholder="Email">
</label>
<label class="item item-input">
<input type="password" ng-model="user.password" placeholder="Password">
</label>
<label class="item item-input">
<input type="text" ng-model="user.name" placeholder="First Name">
</label>
<label class="item item-input item-stacked-label">
<span class="input-label">Date of Birth</span>
<input type="date" ng-model="user.dob">
</label>
</div>
<div class="assertive" ng-show="error.message">{{error.message}}</div>
<button class="button button-block button-stable" ng-click="register()">
CREATE ACCOUNT
</button>
By creating an account you agree to the Terms of Use and Privacy Policy.
</ion-content>
</ion-view>
controllers.js
angular.module('ionicParseApp.controllers', [])
.controller('AppController', function($scope, $state, $rootScope, $ionicHistory, $stateParams) {
if ($stateParams.clear) {
$ionicHistory.clearHistory();
$ionicHistory.clearCache();
}
$scope.logout = function() {
Parse.User.logOut();
$rootScope.user = null;
$rootScope.isLoggedIn = false;
$state.go('welcome', {
clear: true
});
};
})
.controller('WelcomeController', function($scope, $state, $rootScope, $ionicHistory, $stateParams) {
if ($stateParams.clear) {
$ionicHistory.clearHistory();
$ionicHistory.clearCache();
}
$scope.login = function() {
$state.go('app.login');
};
$scope.signUp = function() {
$state.go('app.register');
};
if ($rootScope.isLoggedIn) {
$state.go('app.home');
}
})
.controller('HomeController', function($scope, $state, $rootScope) {
if (!$rootScope.isLoggedIn) {
$state.go('welcome');
}
})
.controller('LoginController', function($scope, $state, $rootScope, $ionicLoading) {
$scope.user = {
username: null,
password: null
};
$scope.error = {};
$scope.login = function() {
$scope.loading = $ionicLoading.show({
content: 'Logging in',
animation: 'fade-in',
showBackdrop: true,
maxWidth: 200,
showDelay: 0
});
var user = $scope.user;
Parse.User.logIn(('' + user.username).toLowerCase(), user.password, {
success: function(user) {
$ionicLoading.hide();
$rootScope.user = user;
$rootScope.isLoggedIn = true;
$state.go('app.home', {
clear: true
});
},
error: function(user, err) {
$ionicLoading.hide();
// The login failed. Check error to see why.
if (err.code === 101) {
$scope.error.message = 'Invalid login credentials';
} else {
$scope.error.message = 'An unexpected error has ' +
'occurred, please try again.';
}
$scope.$apply();
}
});
};
$scope.forgot = function() {
$state.go('app.forgot');
};
})
.controller('ForgotPasswordController', function($scope, $state, $ionicLoading) {
$scope.user = {};
$scope.error = {};
$scope.state = {
success: false
};
$scope.reset = function() {
$scope.loading = $ionicLoading.show({
content: 'Sending',
animation: 'fade-in',
showBackdrop: true,
maxWidth: 200,
showDelay: 0
});
Parse.User.requestPasswordReset($scope.user.email, {
success: function() {
// TODO: show success
$ionicLoading.hide();
$scope.state.success = true;
$scope.$apply();
},
error: function(err) {
$ionicLoading.hide();
if (err.code === 125) {
$scope.error.message = 'Email address does not exist';
} else {
$scope.error.message = 'An unknown error has occurred, ' +
'please try again';
}
$scope.$apply();
}
});
};
$scope.login = function() {
$state.go('app.login');
};
})
.controller('RegisterController', function($scope, $state, $ionicLoading, $rootScope) {
$scope.user = {};
$scope.error = {};
$scope.register = function() {
// TODO: add age verification step
$scope.loading = $ionicLoading.show({
content: 'Sending',
animation: 'fade-in',
showBackdrop: true,
maxWidth: 200,
showDelay: 0
});
var user = new Parse.User();
user.set("username", $scope.user.email);
user.set("password", $scope.user.password);
user.set("email", $scope.user.email);
user.signUp(null, {
success: function(user) {
$ionicLoading.hide();
$rootScope.user = user;
$rootScope.isLoggedIn = true;
$state.go('app.home', {
clear: true
});
},
error: function(user, error) {
$ionicLoading.hide();
if (error.code === 125) {
$scope.error.message = 'Please specify a valid email ' +
'address';
} else if (error.code === 202) {
$scope.error.message = 'The email address is already ' +
'registered';
} else {
$scope.error.message = error.message;
}
$scope.$apply();
}
});
};
})
.controller('MainController', function($scope, $state, $rootScope, $stateParams, $ionicHistory) {
if ($stateParams.clear) {
$ionicHistory.clearHistory();
}
$scope.rightButtons = [{
type: 'button-positive',
content: '<i class="icon ion-navicon"></i>',
tap: function(e) {
$scope.sideMenuController.toggleRight();
}
}];
$scope.logout = function() {
Parse.User.logOut();
$rootScope.user = null;
$rootScope.isLoggedIn = false;
$state.go('welcome', {
clear: true
});
};
$scope.toggleMenu = function() {
$scope.sideMenuController.toggleRight();
};
});
apps.js
// setup an abstract state for the tabs directive
.state('welcome', {
url: '/welcome?clear',
templateUrl: 'templates/welcome.html',
controller: 'WelcomeController'
})
.state('app', {
url: '/app?clear',
abstract: true,
templateUrl: 'templates/menu.html',
controller: 'AppController'
})
.state('app.home', {
url: '/home',
views: {
'menuContent': {
templateUrl: 'templates/home.html',
controller: 'HomeController'
}
}
})
.state('app.login', {
url: '/login',
views: {
'menuContent': {
templateUrl: 'templates/login.html',
controller: 'LoginController'
}
}
})
.state('app.forgot', {
url: '/forgot',
views: {
'menuContent': {
templateUrl: 'templates/forgotPassword.html',
controller: 'ForgotPasswordController'
}
}
})
.state('app.register', {
url: '/register',
views: {
'menuContent': {
templateUrl: 'templates/register.html',
controller: 'RegisterController'
}
}
});
$urlRouterProvider.otherwise('/welcome');
})
.run(function ($state, $rootScope) {
Parse.initialize('**hidden**', '**hidden**');
var currentUser = Parse.User.current();
$rootScope.user = null;
$rootScope.isLoggedIn = false;
if (currentUser) {
$rootScope.user = currentUser;
$rootScope.isLoggedIn = true;
$state.go('app.home');
}
});