(Webpack failing to build?) Firebase DB in different levels of Vue components - firebase

I'm trying to set up a vue-fire app using single file Vue components.
I'm using the standard (full) Vue-cli Webpack template available on the official site.
I have firebase loaded in App.vue like this:
let config = {
...
};
let app = Firebase.initializeApp(config);
let db = app.database();
let usersRef = db.ref('users');
...
export default {
name: 'app',
data () {
return {
login: {
email: '',
password: ''
},
newUser: {
email: '',
password: ''
},
showRegister: false
}
},
firebase: {
users: usersRef,
},
...
}
I'm using Vue-router and my routes are set up like this:
import Vue from 'vue'
import Router from 'vue-router'
import Home from '#/components/Home'
import News from '#/components/News'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/news',
name: 'News',
component: News
}
]
})
I would like to be able to access my Firebase app in the 'News' component. The problem is that if I include the entire Firbase setup in the News.vue file, I get the error:
[DEFAULT]: Firebase: Firebase App named '[DEFAULT]' already exists (app/duplicate-app).
The recommended solution is to export the initialized app's database in App.vue and import it in the child component. So I add this to the bottom of my App.vue script:
module.exports.FBApp = app.database();
And this to News.vue:
import FBApp from '../App.vue'
let usersRef = FBApp.ref('users')
But now I am getting the following error:
TypeError: __WEBPACK_IMPORTED_MODULE_0__App_vue___default.a.ref is not a function
Does anyone know how to do this? Surely it can't be too hard.

Create a db.js file like the following alongside app.vue.
import firebase from 'firebase'
var config = {
apiKey: 'xxxxx'
authDomain: 'xxxxx'
databaseURL: 'xxxxx'
projectId: 'xxxxx'
storageBucket: 'xxxxx'
messagingSenderId: 'xxxxx'
}
const firebaseApp = firebase.initializeApp(config)
const db = firebaseApp.database()
export default db
In your main.js:
import Vue from 'vue'
import App from './App'
import router from './router'
import VueFire from 'vuefire'
// explicit installation required in module environments
Vue.use(VueFire)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
And now in any component, eg:
<template>
<span>
{{ news }}
</span>
</template>
<script>
import db from '../db'
export default {
data: function () {
return {
users: [],
sample: []
}
},
firebase: function () {
return {
news: db.ref('news')
}
}
}
</script>

Related

unresolved variable $firebaseRefs vue js

I have an add function to add movies to firebase database
methods: {
add() {
this.$firebaseRefs.movies.push({
name: this.newItem.name,
price: this.newItem.genre,
rating: this.newItem.rating,
reviews: this.newItem.reviews,
cast: this.newItem.cast,
});
this.newItem.name = '';
this.newItem.genre = '';
this.newItem.rating = '';
this.newItem.reviews= '';
this.newItem.cast= '';
this.$router.push('/dashboard')
}
}
}
But am getting an error Unresolved variable $firebaseRefs and when I try to add the route changes to
http://localhost:8080/add?
I have imported that
import { db } from '../db';
db.js
import * as firebase from "firebase";
import store from "./store";
let config={
apiKey: "AIzaSyDQ2dXBMuIJ2EBYeVqucJpOF33C0tsFlLk",
authDomain: "tv-show-tracker-9899e.firebaseapp.com",
databaseURL: "https://tv-show-tracker-9899e.firebaseio.com",
projectId: "tv-show-tracker-9899e",
storageBucket: "tv-show-tracker-9899e.appspot.com",
messagingSenderId: "433917891798",
appId: "1:433917891798:web:bb35a74ae42e6db339a577"
};
let app = firebase.initializeApp(config);
export const db = app.database();
// eslint-disable-next-line no-unused-vars
let firebaseRefs = db.ref('movies');
firebase.auth().onAuthStateChanged(user => {
store.dispatch("fetchUser", user);
});
Below is the main.js file
main.js
import Vue from 'vue'
import App from './App.vue'
import router from "./routes/route.js";
import store from "./store";
Vue.config.productionTip = false;
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app')
As explained in the vuefire documentation, you need to install Vuefire as a Vue plugin. Therefore, since you use the Realtime Database, you need to adapt your main.js file as follows
import Vue from 'vue'
import App from './App.vue'
import router from "./routes/route.js";
import store from "./store";
import { rtdbPlugin } from 'vuefire'
Vue.use(rtdbPlugin)
Vue.config.productionTip = false;
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app')
Do not forget to install the latest version of Vuefire as follows (see doc):
npm install vuefire

Vuex and API calls

I'm trying to implement Vuex in an app I'm building to learn more about Vue.js. The idea is pretty simple: retrieving user information and a list of items (everything is stored on Firebase).
I get the idea of Vuex, but the tutorials I can find only rely on data stored locally in the store. I can't get my head around how it would work when the data in the store has to be kept in sync with an external database.
Did I totally miss something? or maybe is Vuex not the best solution for that?
If you want "the data in the (Vue.js) store to be kept in sync with an external (Firestore) database", you could do as follows, taking advantage of the onSnapshot() method which "attaches a listener for QuerySnapshot events".
Let's imagine you have a cities collection in your Firestore database, and each document of this collection has a field name, which holds the city name.
First, declare the Firebase config in a firebaseConfig.js file:
firebaseConfig.js
import firebase from 'firebase/app';
import 'firebase/firestore';
// firebase init goes here
const config = {
apiKey: 'xxxxxxxxxxxxxxxxxx',
authDomain: 'xxxxxxxxx.firebaseapp.com',
databaseURL: 'xxxxxxxxxxxxxxxxxx',
projectId: 'xxxxxxxxxxxxxxxxxx'
};
firebase.initializeApp(config);
const db = firebase.firestore();
export { db };
Then set-up your Vuex store as follows:
store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
cities: []
},
mutations: {
SET_CITIES(state, val) {
state.cities = val;
}
},
actions: {
//You may add here an action that would commit the SET_CITIES mutation
}
});
Then, modify the main.js file as follows:
main.js
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
const fb = require('./firebaseConfig.js');
Vue.config.productionTip = false;
new Vue({
router,
store,
beforeCreate() {
fb.db.collection('cities').onSnapshot(querySnapshot => {
var c = [];
querySnapshot.forEach(doc => {
c.push({
id: doc.id,
name: doc.data().name
});
});
store.commit('SET_CITIES', c);
});
},
render: h => h(App)
}).$mount('#app');
You are all set! Just try getting the cities array in a Component, as follows:
HelloWorld.vue
<template>
<div>
<ul>
<li v-for="c in cities" v-bind:key="c.id">{{ c.name }}</li>
</ul>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "HelloWorld",
computed: {
...mapState(["cities"])
}
};
</script>
and try adding, removing or modifying records in the database.

How to configure firebase as nuxt plugin?

I am trying to configure firebase in nuxt as a plugin. I have to make the nuxtInitServer call in store because the env variables are from sharedEnv.
When the login method is invoked on the login page, I get the error:
Uncaught TypeError: _plugins_firebase__WEBPACK_IMPORTED_MODULE_3__.default.auth is not a function
store/index.js
const getSharedEnv = () =>
process.server
? {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.FIREBASE_DB_URL,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.FIREBASE_MESSAGE_SENDER_ID
}
: {}
...
export const actions = {
nuxtServerInit({ commit, state, store, dispatch }, { req }) {
if (process.server) {
commit('setSharedEnv', getSharedEnv())
}
}
}
plugins/firebase.js
import Vue from 'vue'
import firebase from 'firebase/app'
Vue.use(firebase)
export default context => {
// perform a store action manually to have access to `sharedEnv` object
context.store.dispatch('nuxtServerInit', context)
const env = { ...context.store.state.sharedEnv }
if (!firebase.apps.length) {
console.log('initialize firebase...')
firebase.initializeApp(env)
}
return firebase
}
pages/login/index.vue
<script>
import firebase from '#/plugins/firebase'
export default {
name: 'login',
data() {
return {
email: '',
password: ''
}
},
methods: {
login: function() {
let additionalClaims = {
premiumAccount: true
}
console.log('login page')
console.log(firebase)
firebase
.auth()
.signInWithEmailAndPassword(this.email, this.password)
.then(
response => {
...
You need to also import the firebase/auth library if you need the auth feature
i.e.
import firebase from 'firebase/app';
import 'firebase/auth';

invalid Firebase binding source with vuefire

I'm starting with vue and firebase, but now I have this error when I show what I already have in my database.
main.js
import vueFire from 'vuefire';
import firebase from 'firebase';
Vue.use(vueFire);
let config = {
apiKey: "mykey",
authDomain: "mydomain",
databaseURL: "myurl",
projectId: "my",
storageBucket: "bucket",
messagingSenderId: "number"
};
let application = firebase.initializeApp(config)
let db = application.database()
let notificationsdb = db.ref('notifications')
export { notificationsdb };
component.vue
import { notificationsdb } from '../main';
export default {
name: 'Notifications',
firebase: {
notifi: notificationsdb
},
data() {
return{
newNoti: {
name: '',
text: ''
},
}
},
methods: {
addNoti: function(){
notificationsdb.push(this.newNoti);
this.newNoti.name = '',
this.newNoti.text = ''
toastr.success('Notificación creada');
},
deleteNoti: function(noti){
notificationsdb.child(noti['.key']).remove();
toastr.success('Notificación eliminada');
}
}
}
If I delete this line of code and save it and then put it back, I keep changes, it works. But if I press F5 it stops working
firebase: {
notifi: notificationsdb
},
and he sent me the following error
[Vue warn]: Error in created hook: "Error: VueFire: invalid Firebase binding source."
So, I'm assuming you started your project with something like:
vue init webpack myProject
Basically what's happening is your component doesn't have access to the data from firebase the first time you load it. It takes some time for you to make an edit (time in which the server request is completing). Then when you press save, it triggers the HMR, and your site reloads with the data it's expecting.
Try making these changes (although you should move this config stuff into a separate file (like firebaseDB.js for example)):
// let db = application.database()
// let notificationsdb = db.ref('notifications')
// export { notificationsdb }
export default application.database()
Then in component.vue:
[...]
import db from '../firebaseDB'
[...]
firebase: {
notifi: db.ref('notifications')
},
[...]
You'll probably want to add a loading state var to this component, and so on. Good luck!

Vue.Js - Firebase functions cannot be used on components

I was using Vue Resource in posting data from my web app to the firebase. but then, I just found out that I need to use firebase integration to upload IMAGES in the firebase storage. so I integrated it in my src/main.js
import Vue from 'vue'
import VueResource from 'vue-resource'
import VueRouter from 'vue-router'
import * as firebase from 'firebase'
import App from './App.vue'
import Routes from './routes'
Vue.use(VueResource);
Vue.use(VueRouter);
const router = new VueRouter({
routes: Routes,
mode: 'history'
});
new Vue({
el: '#app',
render: h => h(App),
router: router,
created () {
firebase.initializeApp({
apiKey: 'AIzaSyDhdEhcLPfGqo5_msnhVKWH9BkZNOc6RYw',
authDomain: 'nots-76611.firebaseapp.com',
databaseURL: 'https://nots-76611.firebaseio.com',
projectId: 'nots-76611',
storageBucket: 'gs://nots-76611.appspot.com'
})
}
})
but when I tried to use it in one of my components' methods:
methods: {
post: function(){
//for(var i = 0; i < this.tailors.length; i++){
// if(this.$route.params.id == this.tailors[i].id)
// this.ready_to_wear.tailor_name = this.tailors[i].tName;
//}
//this.$http.post('https://nots-76611.firebaseio.com/ready_to_wear.json', this.ready_to_wear);
let key
firebase.database().ref('ready_to_wears').push(this.ready_to_wear)
.then((data) => {
key = data.key
return key
})
.then(key => {
const filename = this.image.name
const ext = filename.slice(filename.lastIndexOf('.'))
return firebase.storage().ref('rtws/' + key + '.' + ext).put(this.image)
})
.then(fileData => {
imageUrl = fileData.metadata.downloadURLs[0]
return firebase.database().ref('ready_to_wears').child(key).update({rtwImg: imageUrl})
});
}
}
.. it says in the console log that 'firebase' is not defined
I'm guessing that firebase functions can't be used in the components even though it is integrated in the main.js
How do I make use of it in the components? is there any other way around it?
You don't appear to be using VueFire, which I believe exposes firebase through a Vue prototype property as $firebase. However, you can do it yourself manually.
import Vue from 'vue'
import VueResource from 'vue-resource'
import VueRouter from 'vue-router'
import * as firebase from 'firebase'
import App from './App.vue'
import Routes from './routes'
Vue.prototype.$firebase = firebase
After that, firebase will be available in every Vue or component as this.$firebase.
methods: {
post: function(){
this.$firebase.database().ref() ... etc ...
}
}

Resources