Firebase angularfire in new firebase - angularjs

I have an angular app, which utilizes the angularFire library. It is stated in the firebase documentation that angularfire is supported https://firebase.google.com/support/guides/firebase-web#update_your_firebase_libraries_numbered
I have updated firebase and angularfire to the latest version.
BEFORE: //This works :-)
// *** DataService ***
var root = new Firebase(FIREBASE_URL);
var service = {
root: root,
items: root.child('items'),
tastings: root.child('tastings'),
users: root.child('users'),
votes: root.child('votes')
};
return service;
// *** Controller ***
$scope.tastings = $firebaseArray(dataService.tastings);
AFTER: //This does not work :-(
// *** app.js ***
.run(function (FIREBASE_CONFIG) {
firebase.initializeApp(FIREBASE_CONFIG);
});
// *** DataService ***
var root = firebase.database().ref();
var service = {
root: root,
items: root.child('items'),
tastings: root.child('tastings'),
users: root.child('users'),
votes: root.child('votes')
};
return service;
// *** Controller ***
$scope.tastings = $firebaseArray(dataService.tastings);
The error I am getting: "Must pass a valid Firebase reference to $firebase (not a string or URL)"
It looks like a firebase reference in chrome console when i evaluate dataService.tastings, though there are new properties like database, which has been added.

AngularFire is now officially updated to support Firebase 3.x.x :)

Yes, AngularFire is supported with google's new firebase 3 and above. Along with that you can get the detailed documentation of it on :
GitHub : https://github.com/firebase/angularfire

I'm using the latest version in one of my projects and it works fine so you should have something like this:
/// Main configuration of Firebase
var config = {
apiKey: "AIzaSyDcPq_z9vh4CidkzFDyerRK0ZS7gs2Sj14",
authDomain: "citytimer-90920.firebaseapp.com",
databaseURL: "https://citytimer-90920.firebaseio.com",
storageBucket: "citytimer-90920.appspot.com",
messagingSenderId: "497040832817"
};
firebase.initializeApp(config);
This part is pure Javascript so you don't need to include it in an Angular file.
Then those are the Angular files I'm using.
/// Database service
function firebaseDataService() {
var root = firebase.database().ref();
var service = {
root: root,
requests: root.child('requests'),
places: root.child('places')
};
return service;
}
As you can see my service looks like yours.
/// Specific service to retrieve data
function cityTimerService($firebaseArray, firebaseDataService, $firebaseObject, $rootScope, $q, $http) {
var service = {
getRequestsByUser: getRequestsByUser,
};
return service;
function getRequestsByUser(uid) {
if (!requests) {
requests = $firebaseArray(firebaseDataService.requests.child(uid).child('userRequests'));
}
return requests;
}
}
Basically you don't longer need to provide the FIREBASE_URL because it's part of the configuration object. For the record you can get this configuration object from your Firebase console.
If you want to take a closer look on the code I have in my project you can do it here.

Related

Getting a firebase.database is not a function? [duplicate]

I am trying to upgrade from earlier firebase version to the latest in my ionic project. I followed this tutorial for upgrade. In step 4 from this page I am stuck on the last statement firebase.database().ref();.
Error message
TypeError: firebase.database is not a function
Below is my code. Kindly help.
...
// Initialize Firebase
this.config = {
apiKey: "some-api-key",
authDomain: "myapp.firebaseapp.com",
databaseURL: "https://myapp.firebaseio.com",
storageBucket: "project-somenumber.appspot.com",
};
...
this.authWithOAuthPopup = function(type) {
var deferred = $q.defer();
console.log(service.config); // ---> Object {apiKey: "some-api-key", authDomain: "myapp.firebaseapp.com", databaseURL: "https://myapp.firebaseio.com", storageBucket: "project-somenumber.appspot.com"}
firebase.initializeApp(service.config);
console.log(firebase); // ---> Object {SDK_VERSION: "3.0.5", INTERNAL: Object}
service.rootRef = firebase.database().ref(); //new Firebase("https://rsb2.firebaseio.com"); ---> I am getting error on this line "TypeError: firebase.database is not a function"
service.rootRef.authWithOAuthPopup(type, function(error, authData) {
if (error) {
service.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(service.authError);
} else {
service.authData = authData;
console.log("Authenticated successfully with payload:", authData);
deferred.resolve(service.authData);
}
return deferred.promise;
});
return deferred.promise;
}
var service = this;
Update
After adding latest database library this questions problem is solved.
Updating my code here
this.authWithOAuthPopup = function(type) {
var deferred = $q.defer();
console.log(service.config);
firebase.initializeApp(service.config);
console.log(firebase);
service.rootRef = firebase.database(); //.ref(); //new Firebase("https://rsb2.firebaseio.com");
var provider = new firebase.auth.FacebookAuthProvider();
firebase.auth().signInWithRedirect(provider);
firebase.auth().getRedirectResult().then(function(result) {
if (result.credential) {
// This gives you a Facebook Access Token. You can use it to access the Facebook API.
var token = result.credential.accessToken;
console.log(result);
// ...
}
// The signed-in user info.
var user = result.user;
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});
return deferred.promise;
}
I ran into this with Ionic and it turned out that I wasn't including everything when using the latest Firebase Client. If you've included Firebase as firebase-app, then the Database and Auth pieces need to be required separately since they aren't bundled when including Firebase in this way.
Add the following to your index.html after you include firebase-app.js
<script src="https://www.gstatic.com/firebasejs/3.1.0/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/3.1.0/firebase-database.js"></script>
Obviously you don't need to use the CDN, you could use bower (probably the preferred way with Ionic) or NPM with Browserify.
// Browserify Setup
var firebase = require('firebase/app');
require('firebase/auth');
require('firebase/database');
Snippet below taken from the Firebase Web Setup Docs
You can reduce the amount of code your app uses by just including the features you need. The individually installable components are:
firebase-app - The core firebase client (required).
firebase-auth - Firebase Authentication (optional).
firebase-database - The Firebase Realtime Database (optional).
firebase-storage - Firebase Storage (optional).
From the CDN, include the individual components you need (include firebase-app first)
A bit late to the party, but in case some one wanted to know the syntax in angular, (or Ionic 4) just add this to your .module.ts file (Note, as peterb mentioned, the /database import)
import { AuthService } from './auth.service';
import { AngularFireAuthModule } from 'angularfire2/auth';
import { AngularFireDatabaseModule } from 'angularfire2/database';
#NgModule({
imports: [
AngularFireAuthModule,
AngularFireDatabaseModule,
AngularFireModule.initializeApp(environment.firebase),
],
providers: [
]
})
i solved this issue by giving the url in the constructor
firebase.database('https://123.firebaseio.com')
First, make sure you are using
<script src="https://www.gstatic.com/firebasejs/3.1.0/firebase.js"></script>
Firebase authWithOAuthPopup has changed a little bit in the new version.
Now you don't use the ref to call authentication methods. You should be using firebase.auth() insted.
var auth = firebase.auth();
var provider = new firebase.auth.TwitterAuthProvider();
auth.signInWithPopup(provider).then(function(result) {
// User signed in!
var uid = result.user.uid;
}).catch(function(error) {
// An error occurred
});
Also faced this problem on #angular/firebase 5.1.2, solved when updated #angular/cli and all dependencies to the latest version.
For people facing similar error(this._database.native.on is not a function) in React-native -
run the pod install - after adding firebase new service(database/auth ...)
terminate the metro bundler and restart it using "npx react-native start"
run "npx react-native run-ios"
This will create a new build and the error should be gone.
Ref: https://github.com/invertase/react-native-firebase/issues/3379
Use
var firebase = require('firebase/app');
require('firebase/database');
npm install --save firebase
Then:
require("firebase/database");
You need to add all of the firebase products you are using by way of require() as shown above.
I have the same error -firebase.database is not a function- but with different situation you just need to add
above and the link of javascript that contain the Firebase configuration.
You may also try to use the defer Attribute in your script as it will not load the scripts until page elements are loaded.

Firebase - Angularjs handle email verification

I use firebase and Angularjs on my web app. I have a factory below serving to all my app modules:
.factory('Auth', ["$firebaseAuth",
function($firebaseAuth) {
return $firebaseAuth();
}
]);
It is critical for me (in fact it is the easiest and only way I know) to check pages if auth required or not. So I put this code on each module config in $stateProvider :
resolve: {
"currentAuth": ["Auth", function(Auth) {
return Auth.$requireSignIn();
}]
I want to use firebase email verification and according to documents I need to do so:
var app = firebase.initializeApp(config);
var auth = app.auth();
...
function handleVerifyEmail(auth, actionCode, continueUrl) {
auth.applyActionCode(actionCode).then(function(resp) {
...
}).catch(function(error) {
...
});
}
But then it returns error:
{code: "app/duplicate-app", message: "Firebase: Firebase App named
'[DEFAULT]' already exists (app/duplicate-app).",
I wanted to try with the factory Auth.applyActionCode but there is no such method. How can I solve this problem?
make sure you're not calling the initialize method more than once. see: github.com/Polymer/polycasts/issues/16 for more details.

Loopback Remote Method and Firebase Admin NodeJS

I am currently trying to create a remote method in loopback that will query a firebase database using the Firebase Admin SDK in NodeJS.
It works, but the issue I am having is that I am unable to make it realtime. It keeps crashing with an error pointing to the callback function being called more than once.
Here is a snippet of the code for my remote method:
'use strict';
module.exports = function(Scusers) {
var admin = require("firebase-admin");
Scusers.listItems = function(cb) {
// Get a database reference
var db = admin.database();
var ref = db.ref("users");
// Attach an asynchronous callback to read the data at our posts reference
var items = [];
// return list of users ordered by key and push each object into an array
ref.orderByKey().on("value", function(snapshot) {
snapshot.forEach(function(data) {
items.push(data.val());
});
// return array
cb(null, items);
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
};
}
If I change this line:
ref.orderByKey().on
for:
ref.orderByKey().once
It works, but on my front-end which is coded in AngularJS, it won't see the changes unless I manually call a refresh.
What should be the best approach to this? Sorry if it is unclear or my approach is wrong, I am so new at this. Thanks!

$firebaseAuth with AngularFire 2.0.1 and Firebase 3.0.5

I am trying to upgrade to Firebase 3 and AngularFire 2.
I have run initializeApp in the config phase of the app:
let firebaseConfig = {
apiKey: config.fbSecret,
authDomain: config.firebaseAuthDomain,
databaseURL: config.firebaseBase
},
fbApp = firebase.initializeApp(firebaseConfig);
let baseRef = firebase.database().ref()
and then 'provided` the baseRef for injection into other modules(as I do in the old version):
$provide.value('FirebaseBase', baseRef);
so that I can inject FirebaseBase into a service module and use e.g. FirebaseBase.child('profile').
That doesn't generate any errors, but I am getting this error in the console when the app runs:
angular.js:4576 Uncaught Error: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp().
There is no indication of where the error comes from, but I have some authentication code in the run phase:
$firebaseAuth.$onAuthStateChanged(..
and I'm guessing that it might come from there. I have tried to follow the migration guides but there doesn't seem to be any real-life example and it is not clear to me how the new AngularFire ties in with firebase.initializeApp.
Is there a sample app anywhere? Am I missing something?
you need to call the initialization in the beginning of the run block in your angular code since you are trying to authorize in there, I made this mistake in a few of my earlier integrations of Firebase
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services', 'ngCordova'])
.run(function ($ionicPlatform, FirebaseDB, $rootScope, $state) {
FirebaseDB.initialize();
// for authentication, managing the state if error..
$rootScope.$on('$stateChangeError',
function (event, toState, toParams, fromState, fromParams, error) {
// if the error is "NO USER" the go to login state
if (error === "NO USER") {
event.preventDefault();
$state.go('login', {});
}
});
})
in my firebaseService
.factory('FirebaseDB', function ($q, $state, $timeout) {
var instance, storageInstance, unsubscribe, currentUser = null
var initialized = false
return {
initialize: function () {
// Not initialized so... initialize Firebase
var config = {
//SET YOUR CONFIG BLOCK HERE
};
// initialize database and storage
instance = firebase.initializeApp(config);
storageInstance = firebase.storage();
// listen for authentication event, dont start app until I
// get either true or false
unsubscribe = firebase.auth().onAuthStateChanged(function (user) {
currentUser = user
console.log("got user..", currentUser);
})
},
}
})
If you put it in the Run phrase it will fix it.

I am using MEAN.IO stack, why can't I hit my data-access layer using require?

So, I am using mean.io and for some reason, my routes.js never hits my 'index.all' method, or the 'exports.all' function, even though I require the functions from the server-side controller. Also, my routing is done using angular-ui-router. Does anybody know how to call a backend method from routing in MEAN.IO? I keep using:
'use strict';
module.exports = function(System, app, auth, database) {
// Home route
var index = require('../controllers/index');
app.route('/test').get(index.all);
app.route('/')
.get(index.render);
};
I would like to hit 'index.all' but even if I navigate to /test, it still gets
index.render. Does anybody know why?
Here is the controllers file:
'use strict';
var mean = require('meanio');
var mongoose = require('mongoose');
var Composition = mongoose.model('Composition');
exports.render = function(req, res) {
console.log(req.user);
var modules = [];
// Preparing angular modules list with dependencies
for (var name in mean.modules) {
modules.push({
name: name,
module: 'mean.' + name,
angularDependencies: mean.modules[name].angularDependencies
});
}
function isAdmin() {
return req.user && req.user.roles.indexOf('admin') !== -1;
}
// Send some basic starting info to the view
res.render('index', {
user: req.user ? {
name: req.user.name,
_id: req.user._id,
username: req.user.username,
roles: req.user.roles
} : {},
modules: modules,
isAdmin: isAdmin,
adminEnabled: isAdmin() && mean.moduleEnabled('mean-admin')
});
};
exports.all = function(req, res) {
console.log(req.user);
Composition.find({user: req.user}, 'title description').sort('-created').populate('user', 'name username').exec(function(err, compositions) {
if (err) {
return res.jsonp(500, {
error: 'Cannot list the compositions'
});
}
res.jsonp(compositions);
});
};
Is this a front-end or backend problem? Thanks for any advice that might be helpful.
You are navigating. So are you hitting the link in the browser url? Then you should try localhost:3000/test instead of localhost:3000/#!/test.
The urls of the form localhost:3000:/#!/<something> are angular routes. Look up angular routing and views. It is better to use angular views than server side rendering. Do angular routing for test and add a view corresponding to it. Fetch the dynamic data in the view using the regular $http.get calls.
Check this tutorial for routing and adding views in angular

Resources