I have implemented Facebook and Google sign in using ionic with Firebase. My setup includes 2 services - FirebaseService.js
, AppService.js
, and a controller dashboard.js
. I am trying to receive the OAuth response in the controller.
What would be the most efficient way to achieve this? I have encountered similar scenarios before and I am looking for an optimal solution.
In my previous approach, I utilized a notifier (called when data is available) and listener:
/** notify for Auth data response */
this.authDataAvailable = function() {
$rootScope.$emit("auth-data-available");
}
/** subscribe to this listener when the aggregated data response is available */
this.authDataAvailableListener = function(scope, callback, isDestroy) {
var handler = $rootScope.$on("auth-data-available", callback);
if (isDestroy)
scope.$on("$destroy", handler);
}
/** subscribing to the above listener */
$scope.authDataResponseListener($scope, function responseAvailable() {
//auth response available at this point
}, true);
FirebaseService.js
function FirebaseService($q) {
this.appRef;
this.authData;
this.getRef = function() {
return this.appRef;
}
this.authWithOAuthPopup = function(type) {
var deferred = $q.defer();
this.appRef = new Firebase("https://lola.firebaseio.com");
this.appRef.authWithOAuthPopup(type, function(error, authData) {
if (error) {
this.authError = error;
switch (error.code) {
case "INVALID_EMAIL":
console.log("The specified user account email is invalid.");
break;
case "INVALID_PASSWORD":
console.log("The specified user account password is incorrect.");
break;
case "INVALID_USER":
console.log("The specified user account does not exist.");
break;
default:
console.log("Error logging user in:", error);
}
deferred.resolve(this.authError);
} else {
this.authData = authData;
console.log("Authenticated successfully with payload:", authData);
deferred.resolve(this.authData);
}
});
deferred.promise;
}
/**
* Write or replace data to a defined path, like messages/users/<username>
*/
this.set = function(child, obj) {
var childRef = this.appRef.child(child);
childRef.set(obj);
}
return {
getRef: this.getRef,
authWithOAuthPopup: this.authWithOAuthPopup
}
}
angular.module("starter.services", []).service('FirebaseService', FirebaseService);
AppService.js
function AppService(FirebaseService, $rootScope) {
this.authData;
/** notify for Auth data response */
this.authDataAvailable = function() {
$rootScope.$emit("auth-data-available");
}
/** subscribe to this listener when the aggregated data response is available */
this.authDataAvailableListener = function() {
var handler = $rootScope.$on("auth-data-response", callback);
if (isDestroy)
scope.$on("$destroy", handler);
}
this.authenticateWithGoogle = function() {
this.authData = FirebaseService.authWithOAuthPopup("google");
this.authDataAvailable();
console.log(this.authData.google.displayName);
}
this.authenticateWithFacebook = function() {
this.authData = FirebaseService.authWithOAuthPopup("facebook");
this.authDataAvailable();
console.log(this.authData.facebook.displayName);
}
this.getAuthData = function() {
return this.authData;
}
return {
authenticateWithGoogle: this.authenticateWithGoogle,
authenticateWithFacebook: this.authenticateWithFacebook,
getAuthData: this.getAuthData
}
}
angular.module('starter.services').service('AppService', AppService);
dashboard.js
function DashCtrl($scope, AppService) {
$scope.user = "";
$scope.openBrowser = function() {
AppService.authenticateWithFacebook();
/*var authData = AppService.getAuthData();
$scope.user = authData.facebook.displayName;
console.log(authData);
console.log($scope.user);*/
}
}
angular.module("starter.controllers", []).controller('DashCtrl', DashCtrl);
During my implementation, I encountered the error "
this.authDataAvailable is not a function
" in AppService.js
while calling this.authDataAvailable();
under this.authenticateWithFacebook
function.
I would appreciate insights on an effective way or best practice to handle such scenarios.
Update
To resolve the issue, I found 2 helpful techniques with assistance from mJunaidSalaat:
Implementing something like the following in my AppService.js:
this.authenticateWithFacebook = function() { FirebaseService.authWithOAuthPopup("facebook") .then(function(data) { service.authData = data; console.log(this.authData); service.authDataAvailable(); console.log(this.authData.facebook.displayName); }, function(err) { console.log(err) }); }
Using an identifier for
this
as its context changes inside any enclosure. Thus, I usedservice
in this scenario.