Skip to content

Instantly share code, notes, and snippets.

@dmattia
Created June 4, 2019 06:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmattia/e219061d1219a854f64944f1e2e9f6d3 to your computer and use it in GitHub Desktop.
Save dmattia/e219061d1219a854f64944f1e2e9f6d3 to your computer and use it in GitHub Desktop.
Vue Firebase Demo
<template>
<div id="app">
<input v-model="path" type="text" />
<FireProvider :config="firebaseConfig">
<FireQuery :path="path" :shouldListen="false">
<template v-slot:error="{ errorMsg }">
Error: {{ errorMsg }}
</template>
<template v-slot:loading>
Loading...
</template>
<template v-slot:success="{ data }">
{{ data }}
</template>
<template v-slot:no-data>
No data found at path: {{ path }}
</template>
</FireQuery>
</FireProvider>
</div>
</template>
<script>
import FireProvider from "./components/FireProvider.vue";
import FireQuery from "./components/FireQuery.vue";
var firebaseConfig = {
apiKey: "AIzaSyB_JLBsyGUznYqg9uzhzTTwNbF8LvPsWGU",
authDomain: "vue-firebase-8bf0c.firebaseapp.com",
databaseURL: "https://vue-firebase-8bf0c.firebaseio.com",
projectId: "vue-firebase-8bf0c",
storageBucket: "vue-firebase-8bf0c.appspot.com",
messagingSenderId: "1059831272108",
appId: "1:1059831272108:web:26351acd73edb651"
};
export default {
name: "app",
components: {
FireProvider,
FireQuery
},
data() {
return {
firebaseConfig,
path: "test"
};
}
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
<template>
<div>
<slot v-if="firebase"></slot>
</div>
</template>
<script>
import * as firebase from "firebase/app";
import "firebase/database";
export default {
name: "FireProvider",
provide() {
return {
firebase: this.firebase
};
},
data() {
return {
firebase: firebase
};
},
created() {
firebase.initializeApp(this.config);
},
props: {
config: Object
}
};
</script>
<template>
<div>
<slot name="loading" v-if="loading"></slot>
<slot name="error" :msg="errorMsg" v-else-if="errorMsg"></slot>
<slot name="success" :data="data" v-else-if="data"></slot>
<slot name="no-data" v-else></slot>
</div>
</template>
<script>
export default {
name: "FireQuery",
inject: ["firebase"],
data() {
return {
data: null,
errorMsg: null,
loading: true,
unsubscribeToListener: null,
ref: null
};
},
methods: {
runQuery() {
this.ref = this.firebase.database().ref(this.path);
if (this.shouldListen) {
this.unsubscribeToListener = this.ref.on(
"value",
this.onSuccess,
this.onError
);
} else {
this.ref
.once("value")
.then(this.onSuccess)
.catch(this.onError);
}
},
onSuccess(snapshot) {
if (snapshot === undefined) {
this.onError(null);
return;
}
this.data = snapshot.val();
this.loading = false;
},
onError(error) {
this.errorMsg = error;
this.loading = false;
}
},
mounted() {
this.runQuery();
},
watch: {
path() {
if (this.unsubscribeToListener != null) {
this.ref.off("value", this.unsubscribeToListener);
}
this.unsubscribeToListener = null;
this.runQuery();
}
},
props: {
path: String,
shouldListen: {
type: Boolean,
default: true
}
}
};
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment