Editing date and updating it in FireBase with vue.js , vuex? - firebase

I'm a beginner in writing vue js. I want to edit an exiting date in the app am working on based on a tutorial video am watching and the new date should be updated both in the app and Firebase when the SAVE button is clicked.
Am getting an error this which i think is not allowing the v-dialog to show but when i change the v-model in the v-date-picker to date which is included in my data as
props: ['meetup'],
data () {
return {
editDialog: false,
editableDate: null,
date: new Date().toISOString().substr(0,10)
}
}
the v-dialog works with no error but i get this error when the v-model is changed from date to editableDate:
vue.runtime.esm.js?ff9b:587 [Vue warn]: Invalid prop: type check failed for prop "value". Expected Array, String, got Date.
vue.runtime.esm.js?ff9b:587 [Vue warn]: Error in data(): "TypeError: dateString.split is not a function"
vue.runtime.esm.js?ff9b:1737 TypeError: dateString.split is not a function
vue.runtime.esm.js?ff9b:587 [Vue warn]: Error in nextTick: "TypeError: Cannot set property 'isDark' of undefined"
TypeError: Cannot set property 'isDark' of undefined
<template>
<v-dialog width="350px" persistent v-model="editDialog" ref="dialog" lazy full-width>
<v-btn accent slot="activator">
Edit Date
</v-btn>
<v-card>
<v-container>
<v-layout row wrap>
<v-flex xs12>
<v-card-title>Edit Meetup Date</v-card-title>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-layout row wrap>
<v-flex xs12>
<v-date-picker v-model="editableDate" style="width: 100%" actions>
<v-spacer></v-spacer>
<template slot-scope="{save, cancel}">
<v-btn
class="blue--text darken-1"
flat
#click.native="editDialog = false">
Close
</v-btn>
<v-btn
class="blue--text darken-1"
flat
#click.native="onSaveChanges">
Save
</v-btn>
</template>
</v-date-picker>
</v-flex>
</v-layout>
</v-container>
</v-card>
</v-dialog>
</template>
scripts
<script>
export default {
props: ['meetup'],
data () {
return {
editDialog: false,
editableDate: null
}
},
methods: {
onSaveChanges () {
const newDate = new Date(this.meetup.date)
const newDay = new Date(this.editableDate).getUTCDate()
const newMonth = new Date(this.editableDate).getUTCMonth()
const newYear = new Date(this.editableDate).getUTCFullYear()
newDate.setUTCDate(newDay)
newDate.setUTCMonth(newMonth)
newDate.setUTCFullYear(newYear)
this.$store.dispatch('updateMeetupData', {
id: this.meetup.id,
date: newDate
})
}
},
created () {
this.editableDate = new Date(this.meetup.date)
}
}
</script>
Have tried all i could but to no avail please i need help
This is my store
updateMeetupData ({commit}, payload) {
commit('setLoading', true)
const updateObj = {}
if (payload.title) {
updateObj.title = payload.title
}
if (payload.description) {
updateObj.description = payload.description
}
if (payload.date) {
updateObj.date = payload.date
}
firebase.database().ref('meetups').child(payload.id).update(updateObj)
.then(() => {
commit('setLoading', false)
commit('updateMeetup', payload)
})
.catch(error => {
console.log(error)
commit('setLoading', false)
})
},

Related

Data not display inside vuetify v-text-field with Nuxt & Firestore

this is a related question which I've asked before:
Get document data from Firestore and show the data into each of the form input field using Nuxt & Vuetify
I want the data that I've submitted to display on the v-text-field input.
As you can see from the image, I can submit my form and I can get the data accordingly.
Name: siradley_ <-- this come from my firestore
but I want it to display inside the v-text-field input, not outside the input field.
Currently, I still not know how to do it.
Any help on how to do it?
<template>
<div>
<v-container>
<v-layout>
<v-flex>
<v-card>
<v-card-text>
<v-form>
<v-layout>
<v-row>
<v-col cols="12" sm="6" md="6" v-for="(test, id) in Test">
<v-text-field
v-model="editedItem.name">{{ test.name }}</v-text-field>
<p>Name: {{ test.name }}</p>
</v-col>
<v-col cols="12" sm="6" md="6">
<v-btn #click="test">Test</v-btn>
</v-col>
</v-row>
</v-layout>
</v-form>
</v-card-text>
</v-card>
</v-flex>
</v-layout>
</v-container>
</div>
</template>
my script
<script>
import firebase from "firebase/app";
import firestore from "#/plugins/firebasetest";
export default {
middleware: "authentication",
layout: 'dashboard',
data: () => ({
Test: [
{
name: '',
}
],
editedItem: {
name: '',
}
}),
created() {
this.readTest();
},
methods: {
readTest() {
this.Test = [];
firestore
.collection('test')
.doc(firebase.auth().currentUser.uid)
.get()
.then((doc) => {
this.Test.push({ ...doc.data(), id: doc.id });
console.log({ ...doc.data(), id: doc.id });
})
},
test() {
var data = {
name: this.editedItem.name,
}
firestore
.collection('test')
.doc(firebase.auth().currentUser.uid)
.set(data)
.then((doc) => {
window.location.reload();
console.log({ ...doc.data, id: doc.id })
})
},
},
}
</script>
you have to update the value editedItem.name in your data object after getting the value from the server.
you have two way data binding set on the v-text-field (i.e. v-model), so you just need to use v-text-field like this:
<v-text-field v-model="editedItem.name" ></v-text-field>
and then in the code after you get the data from the server update the mentioned field in the data:
async getDataFromServerExample() {
const data = await getData();
this.editedItem.name = data.properFieldFromServerResponse;
}
then everything should work fine.
Finally can solve it hehe.
Referring to this Unable to display data in Vue.js form after pulling from Cloud Firestore , I now can display my input data inside my v-text-field.
Here's how I do it:
<v-form>
<v-layout>
<v-row :items="Test">
<v-col cols="12" sm="6" md="6">
<v-text-field
v-model="editedItem.name"></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="6">
<v-btn #click="test">Test</v-btn>
</v-col>
</v-row>
</v-layout>
</v-form>
<script>
import firebase from "firebase/app";
import firestore from "#/plugins/firebasetest";
export default {
middleware: "authentication",
layout: 'dashboard',
data: () => ({
editedItem: {
name: '',
}
}),
created() {
this.readTest();
},
methods: {
readTest() {
let _this = this;
firestore
.collection('test')
.doc(firebase.auth().currentUser.uid)
.get()
.then((doc) => {
if (doc.exists) {
console.log("Document data:", doc.data())
_this.editedItem.name = doc.data().name
} else {
console.log("No Document!");
}
}).catch((error) => {
console.log("Error :(");
})
},
},
}
</script>
I added let _this = this; and _this.editedItem.name = doc.data().name and it works.

Problem using signInWithEmailAndPassword method form Firebase 9 in Nuxt Vue

I'm working on this problem for a few days and I don't know how to solve it.
This is my nuxt login page and I use the new Firebase 9 auth pack to authenticate a user.
I call the signInWithEmailAndPassword method to authenticate.
When I try it with the correct credentials I never get into the first then() of the Promise:
.then((userCredential) => {
alert(userCredential)
this.$store.commit('setUser', userCredential.user)
})
But when I type in the incorrect credentials, I always get the correct error (in the catch) and the second then() is always executed.
I don't understand why I can't log in.
Can anyone help me?
Sorry for the bad English.
My login page: (pages/index.vue)
<template>
<v-container fluid fill-height>
<v-layout align-center justify-center>
<v-flex xs12 sm8 md4>
<v-card class="elevation-12">
<v-toolbar dark color="primary">
<v-toolbar-title>Anmelden</v-toolbar-title>
</v-toolbar>
<v-card-text>
<v-form
id="login-form"
ref="form"
v-model="valid"
lazy-validation
#submit.prevent="emailLogin()"
>
<v-text-field
v-model="formData.email"
:rules="emailRules"
name="email"
label="E-Mail"
counter
required
/>
<v-text-field
v-model="formData.password"
:append-icon="show ? 'mdi-eye' : 'mdi-eye-off'"
:rules="passwordRules"
:type="show ? 'text' : 'password'"
name="password"
label="Passwort"
counter
required
#click:append="show = !show"
/>
</v-form>
</v-card-text>
<v-snackbar
v-model="snackbar"
:timeout="timeout"
>
{{ text }}
<template #action="{ attrs }">
<v-btn
color="yellow accent-2"
text
v-bind="attrs"
#click="snackbar = false"
>
Schließen
</v-btn>
</template>
</v-snackbar>
<v-card-actions>
<v-spacer />
<v-btn
type="submit"
form="login-form"
:disabled="!valid"
block
color="primary"
class="mr-4"
>
Login
</v-btn>
</v-card-actions>
</v-card>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import { auth, signInWithEmailAndPassword } from '#/plugins/firebase'
export default {
data: () => ({
show: false,
valid: true,
snackbar: '',
timeout: 10000,
text: '',
formData: {
email: '',
password: ''
},
emailRules: [
v => !!v || 'E-Mail ist verpflichtend',
v => /.+#.+\..+/.test(v) || 'Keine gültige E-Mail-Adresse'
],
passwordRules: [
v => !!v || 'Passwort ist verpflichtend'
]
}),
methods: {
emailLogin () {
signInWithEmailAndPassword(auth, this.formData.email, this.formData.password)
.then((userCredential) => {
alert(userCredential)
this.$store.commit('setUser', userCredential.user)
})
.catch((error) => {
switch (error.code) {
case 'auth/invalid-email':
this.text = 'Die E-Mail-Adresse ist falsch'
break
case 'auth/user-disabled':
this.text = 'Der User ist deaktiviert'
break
case 'auth/user-not-found':
this.text = 'Kein Account gefunden'
break
case 'auth/wrong-password':
this.text = 'Das Passwort ist falsch'
break
default:
this.text = 'Es ist ein Fehler aufgetreten: ' + error.message
break
}
this.snackbar = true
}).then(() => {
this.formData.email = ''
this.formData.password = ''
this.$refs.form.resetValidation()
this.$router.push('/post')
})
}
}
}
</script>
My firebase setup file: (plugins/firbase.js) --> is registered in nuxt.config.js
import { initializeApp } from 'firebase/app'
import { getFirestore } from 'firebase/firestore'
import { getStorage } from 'firebase/storage'
import { getAuth, signInWithEmailAndPassword, signOut, onAuthStateChanged } from 'firebase/auth'
const firebaseConfig = {
apiKey: 'key',
authDomain: 'domain',
projectId: 'project',
storageBucket: 'bucket',
messagingSenderId: 'message',
appId: 'app',
measurementId: 'measure'
}
const app = initializeApp(firebaseConfig)
const auth = getAuth(app)
const fire = getFirestore(app)
const storage = getStorage(app)
export { auth, fire, storage, signInWithEmailAndPassword, signOut, onAuthStateChanged }

action not found in Vuex store

I'm following a course here:
https://thinkster.io/tutorials/nuxt-js-project/adding-authentication
I am working on adding authentication to my app and have login/logout buttons that partially work with firebase authentication. I can log in fine, but the issue is that when I'm logged in, the action in my Vuex store doesn't seem to run, therefore leaving the user logged in and the state not updating to display the logout button.
default.vue
<template>
<v-app>
<v-navigation-drawer
v-model="drawer"
:mini-variant="miniVariant"
:clipped="clipped"
fixed
app
>
<v-list>
<v-list-item
v-for="(item, i) in items"
:key="i"
:to="item.to"
router
exact
>
<v-list-item-action>
<v-icon>{{ item.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title v-text="item.title" />
</v-list-item-content>
</v-list-item>
<button v-if="!mySession" #click="login">Login</button>
<button v-else #click="logout">Logout</button>
</v-list>
</v-navigation-drawer>
<!-- <v-toolbar fixed app :clipped-left="clipped">
<v-toolbar-side-icon #click="drawer = !drawer"></v-toolbar-side-icon>
<v-tool-bar-title v-text="title"></v-tool-bar-title>
<v-spacer></v-spacer>
<v-toolbar-items>
<v-btn #click="login">Login</v-btn>
<v-btn #click="logout">Logout</v-btn>
</v-toolbar-items>
</v-toolbar> -->
<v-app-bar
:clipped-left="clipped"
fixed
app
>
<v-app-bar-nav-icon #click.stop="drawer = !drawer" />
<v-btn
icon
#click.stop="clipped = !clipped"
>
<v-icon>mdi-application</v-icon>
</v-btn>
<v-btn
icon
#click.stop="fixed = !fixed"
>
<v-icon>mdi-minus</v-icon>
</v-btn>
<v-toolbar-title v-text="title" />
<v-spacer />
</v-app-bar>
<v-content>
<v-container>
<nuxt />
</v-container>
</v-content>
<v-navigation-drawer
v-model="rightDrawer"
:right="right"
temporary
fixed
>
<v-list>
<v-list-item #click.native="right = !right">
<v-list-item-action>
<v-icon light>
mdi-repeat
</v-icon>
</v-list-item-action>
<v-list-item-title>Switch drawer (click me)</v-list-item-title>
</v-list-item>
</v-list>
</v-navigation-drawer>
<v-footer
:fixed="fixed"
app
>
<span>© 2019</span>
</v-footer>
</v-app>
</template>
<script>
import {db} from '#/plugins/firebase'
import firebase from 'firebase/app'
import 'firebase/auth'
export default {
created() {
this.$store.dispatch('setSession');
},
data () {
return {
clipped: false,
drawer: false,
fixed: false,
items: [
{
icon: 'mdi-apps',
title: 'Welcome',
to: '/'
},
{
icon: 'cart',
title: 'Checkout',
to: '/checkout'
}
],
miniVariant: false,
right: true,
rightDrawer: false,
title: 'Vuetify.js'
}
},
methods: {
login() {
console.log('login');
let provider = new firebase.auth.GoogleAuthProvider();
firebase.auth()
.signInWithPopup(provider)
.then(function(result) {
console.log('signed in');
})
.catch(function(error) {
console.log(error);
})
},
logout() {
console.log('logout');
firebase.auth()
.signOut()
.then(() => {
console.log('sign out')
}).catch((error) => {
console.log(error)
})
}
},
computed: {
mySession() {
return this.$store.getters.session;
}
}
}
</script>
store/index.js
import Vuex from 'vuex'
import firebase from 'firebase/app'
import 'firebase/auth'
const createStore = () => {
return new Vuex.Store({
state: {
session: false
},
mutations: {
SET_SESSION(state, session) {
state.session = session;
}
},
getters: {
session: state => state.session
},
actions: {
setSession({commit}) {
firebase.auth().onAuthStateChanged(user => {
console.log(user);
console.log('change');
commit('SET_SESSION', user || false);
})
}
}
})
}
export default createStore
in console I am getting an error message that says:
"[vuex] unknown action type: setSession"
To reiterate, I can login using Google oauth, but when logged in, the state does not change and the logout button does not appear.
Thanks for the help!
Update:
Well now I'm extra confused. I did push updates 15 mins ago but for some reason my store/index.js file is outdated and isn't updating/saving? I have no idea what I'm doing wrong.
When looking at my store/index.js file on Github, it shows the default template:
https://github.com/SIeep/US-kratom/blob/master/US-Kratom/store/index.js
But what I have, and what was just copied from the course I'm taking is:
import Vuex from 'vuex';
import firebase from 'firebase/app';
import 'firebase/auth';
const createStore = () => {
return new Vuex.Store({
state: {
session: false,
products: []
},
mutations: {
SET_SESSION(state, session) {
state.session = session;
},
SET_PRODUCT(state, product) {
state.products = product;
}
},
getters: {
session: state => state.session,
products: state => state.products
},
actions: {
setSession({ commit }) {
firebase.auth().onAuthStateChanged(user => {
commit('SET_SESSION', user || false);
});
},
setProduct({ commit }, products) {
commit('SET_PRODUCT', products);
}
}
});
};
export default createStore;
I am saving the file and everything but it's not updating on Github which is obviously the issue with my app as well.
Erik from Thinkster.io ended up fixing the code for me. Update is here:
[https://github.com/SIeep/US-kratom/commit/bd55deacadfc065edc7df9c1365ae832a32b9b43][1]

Vue js - reload component on database insert

I have the following setup
Component.vue (display db collections as grid in main page)
...
<v-flex v-for="i in items" :key="i.id" xs6 sm3 md3>
<v-card color="primary">
<v-card-text>
<h2
class="font-weight-regular mb-4"
>
{{ i.description }}
</h2>
</v-card-text>
</v-card>
</v-flex>
...
<script>
import { db } from '~/plugins/firebase.js'
export default {
data: () => ({
items: []
}),
props: ['reload'],
watch: {
reload: function (newVal, oldVal) {
this.items = items
alert('changed reload')
}
},
methods: {
firestore() {
db.collection('items')
.get()
.then(querySnapshot => {
const items = []
querySnapshot.forEach(function(doc) {
const item = doc.data()
item.id = doc.id
items.push(useritem)
})
this.items = items
})
.catch(function(error) {
alert('Error getting documents: ' + error)
})
}
}
}
</script>
index.vue (main page that has grid component and button to add new collection)
....
<v-layout mb-4>
<v-btn
#click="submit"
>
Add Item
</v-btn>
</v-layout>
<v-layout mb-4>
<component :reload="reload" />
</v-layout>
....
<script>
import { db } from '~/plugins/firebase.js'
import component from '~/components/Component.vue'
import moment from 'moment'
export default {
components: {
component
},
data() {
return {
description: 'test',
date: moment(),
reload: false
}
},
methods: {
submit() {
db.collection('items')
.add({
description: this.description,
deadline: new Date(moment(this.date)),
status: true
})
.then(docRef => {
this.reload = true
})
.catch(error => {
alert('Error adding document: ', error)
})
}
}
}
</script>
As can be seen, I've added a prop to the component to sort of trigger a reload of data from database whenever a new item is added on the main page using the button.
On successful insert the value changes from false to true. However the component grid does not reload. Refreshing the page shows the new item in grid.
How can i make the component reactive or trigger reload on addition of new item?
In your firestore method in Component.vue, you are using the get method which according to the firestore documentation, only retrieves the data once, it doesn't listen to any change, you'd have to refresh your page to see your updated changes.
However, to listen to changes to your firestore DB and update accordingly on your website, you have to set a listener, Cloud Firestore sends your listener an initial snapshot of the data, and then another snapshot each time the document changes.
methods: {
firestore() {
db.collection("items").onSnapshot(
snapshot => {
const documents = snapshot.docs.map(doc => {
const item = doc.data();
item.id = doc.id;
return item;
});
this.items = documents;
},
error => {
// handle errors
alert("Error getting documents: " + error);
}
);
}

Rendering firestore values in Vue.js

I'm trying to build a simple app and am running into trouble getting Vue rendering data I'm trying to pull from Firestore. Below is the code for a vue page after someone logs in. Essentially I'm just trying to get it to display the name of the person who logged in. Currently I have each user's display name as the document ID for the get() function. Right now, it doesn't even seem like its running the 'firestore()' function since I tried outputting some text to the console at the beginning but I didn't see it. Any idea what's happening here? Thank you!
<template>
<v-container fluid>
<v-layout row wrap>
<v-flex xs12 class="text-xs-center" mt-5>
<h1>Home page</h1>
</v-flex>
<v-flex xs12 class="text-xs-center" mt-3>
<p>Welcome {{ name }}</p>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import firebase from 'firebase'
export default {
data () {
return {
name: ''
}
},
firestore () {
firebase.firestore().collection('user').doc(firebase.auth().currentUser.displayName).get()
.then(doc => {
if (doc) {
var data = doc.data()
return {
name: data.name
}
} else {
console.log('No document exists')
}
}).catch(error => { console.log('Error: ' + error) })
}
}
</script>
You can use created hook for this purpose.
created() {
firebase.firestore().collection('user').doc(firebase.auth().currentUser.displayName).get()
.then(doc => {
if (doc) {
var data = doc.data()
this.name = data.name
} else {
console.log('No document exists')
}
}).catch(error => { console.log('Error: ' + error) })
}
If you're using vuefire, you can do
firestore: {
users: firebase.firestore().collection('user').doc(firebase.auth().currentUser.displayName)
}
then use this.users in your Vue code

Resources