Handling of user status already exists at login - vue.js

I have a form to sign in and another form to sign up, and I have a store file, and when I enter user data, the data is stored in the local storage and VueX.
And all users are stored in the matrix "user".
And now I want to verify when I'm running a login.
If the user already exists, a message that "he already exists" should appear.
How can I solve the problem?
This is store file, in which a set of functions is written and in it there is a "user" array.
store.js:
import Vue from 'vue'
import Vuex from 'vuex'
const LOGIN = "LOGIN";
const LOGIN_SUCCESS = "LOGIN_SUCCESS";
const LOGOUT = "LOGOUT";
import image1 from '../assets/img/image4.jpg'
import image2 from '../assets/img/image2.jpg'
import image3 from '../assets/img/image3.jpg'
import image4 from '../assets/img/insta2.jpg'
Vue.use(Vuex)
export const store = new Vuex.Store({
state:{
isLoggedIn: !!localStorage.getItem('token'),
user:[
{name:'Hiba',
email:'Hiba69#gmail.com',
password:'123442321325'
}
]
},
mutations:{
createUser(state,payload){
state.user.push(payload)
}
},
},
getters:{
loadedUsers(state){
return state.user.sort((userA,userB)=>{
return userA.id >userB.id
})
},
isLoggedIn: state => {
return state.isLoggedIn
}
}
})
This is the signup file, through which you sign up to the site by entering the user's data.
signup.vue:
<template>
<div>
<v-container>
<v-layout row>
<v-flex xs12 sm6 offset-sm3>
<v-card>
<v-img
height="180px"
:src="
'https://cdn.awave.se/wp-content/uploads/sites/3/2019/02/case_greenfood_1new.jpg'
"
></v-img>
<v-card-text>
<v-container>
<form #click="onSignUp">
<v-layout row>
<v-flex xs12>
<v-text-field
name="id"
label="Id"
id="id"
v-model="id"
type="number"
color="#43A047"
required
>
{{ id }}
</v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<v-text-field
name="name"
label="Name"
id="name"
v-model="name"
type="text"
color="#43A047"
required
>
{{ name }}
</v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<v-text-field
name="email"
label="Email"
id="email"
v-model="email"
type="text"
color="#43A047"
required
>
{{ email }}
</v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<v-text-field
name="password"
label="Password"
id="password"
v-model="password"
type="password"
color="#43A047"
required
>
{{ password }}
</v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<v-btn class="green darken-1 color">
Sign up
</v-btn>
</v-flex>
</v-layout>
</form>
</v-container>
</v-card-text>
</v-card>
</v-flex>
</v-layout>
</v-container>
</div>
</template>
<script>
export default {
data() {
return {
id: "",
name: "",
email: "",
password: "",
};
},
computed: {
formIsValid() {
return (
this.id !== "" &&
this.name !== "" &&
this.email !== "" &&
this.password !== ""
);
},
},
watch: {
name(newName) {
localStorage.name = newName;
},
},
methods: {
onSignUp() {
if (!this.formIsValid) {
return;
}
const signup = {
name: this.name,
email: this.email,
password: this.password,
};
console.log(signup);
this.$store.commit("createUser", signup);
const stringifiedData = JSON.stringify(signup);
// console.log("S: ", stringifiedData);
localStorage.setItem("signup", stringifiedData);
console.log("We got : ", JSON.parse(localStorage.getItem("signup")));
},
},
};
</script>
<style scoped>
.color {
color: #fafafa;
}
</style>
This is the login file, through which you log in to the site by entering the user's data.
signin.vue:
<template>
<v-container>
<v-layout row>
<v-flex xs12 sm6 offset-sm3>
<v-card>
<v-card-text>
<v-container>
<form #click="onSignIn">
<v-layout row>
<v-flex xs12>
<v-text-field
name="email"
label="Email"
id="email"
v-model="email"
type="text"
color="#43A047"
required
>
{{ email }}
</v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<v-text-field
name="password"
label="Password"
id="password"
v-model="password"
type="password"
color="#43A047"
required
>
{{ password }}
</v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<v-btn class="green darken-1 color">
Sign In
</v-btn>
</v-flex>
</v-layout>
</form>
</v-container>
</v-card-text>
</v-card>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
export default {
data() {
return {
email: "",
password: "",
};
},
methods: {
onSignIn() {
const signin = {
email: this.email,
password: this.password,
};
console.log(signin);
const stringifiedData = JSON.stringify(signin);
localStorage.setItem("signin", stringifiedData);
console.log("We got : ", JSON.parse(localStorage.getItem("signin")));
},
}
};
</script>
<style scoped>
.color {
color: #fafafa;
}
</style>

You should check if there is an user, when you created the app.
At main.js, you could use something like that;
new Vue({
el: '#app',
router,
store,
render: h => h(App),
created() {
if (localStorage.getItem("user")) {
store.dispatch("autoSignIn", localStorage.getItem("user"));
}
}
And in your vuex store, create autoSignIn method,
autoSignIn({ commit }, payload) {
commit("setLoading", true);
var token = JSON.parse(payload);
var decoded = jwt.verify(token, process.env.VUE_APP_TOKEN);
var loggedUser = {
id: decoded.id,
email: decoded.email
};
commit("setUser", loggedUser);
commit("setLoading", false);
},
And in your signup or login page, if your user state is not null, you can redirect them to the page you want to..
It is better practice to redirect user before rendering the page, so you could use router to check;
{
path: "/login",
beforeEnter: (to, from, next) => {
if (!store.getters.user) {
{
next();
}
} else {
next("/user_secret_page");
}
}
},

Related

How do I capture the value of the prop in the text field?

I have a prop and currently am able to get the data of the prop, Am trying a way to capture the item of the prop when saving the form.
Is there a way where i can take the value and pass if in a hidden text-area and bind the data to the vmodel?
Any help I appreciate.
<v-dialog v-model="dialog" persistent max-width="800">
<template v-slot:activator="{ on }">
<v-btn dark v-on="on" color="primary" round> Make payment </v-btn>
</template>
<v-card>
<v-card-title class="headline primary">
<span class="white--text">Add a new Doctor Payment Record {{ queueId }}</span>
<v-btn icon dark #click.native="dialog = false" absolute right>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<v-card-text>
<users-search
:leave-selected="true"
idOnly
label="Select Doctor"
#results="setDoctor"
>
</users-search>
<div class="row px-3">
<v-autocomplete
class="px-3 col-sm-8"
v-model="expense.bank"
v-if="banks.data"
:items="banks.data"
outline
chips
label="Select bank"
item-text="name"
item-value="id"
>
</v-autocomplete>
<v-text-field
class="px-3 col-sm-8"
outline
flat
v-model="expense.amount"
type="number"
#input="expense.percentage()"
required
label="Amount *"
persistent-hint
/>
</div>
<v-text-field
class="px-3"
outline
flat
v-model="expense.total_paid"
required
label="amount paid"
persistent-hint
/>
<v-text-field
class="px-3"
outline
flat
:value="setQueue"
v-model="expense.queueId"
required
:label=queueId
persistent-hint
/>
<v-alert :value="true" type="error" v-if="errors.any()">
<div v-html="errors.display()"></div>
</v-alert>
<v-layout row wrap>
<v-flex xs12>
<v-btn
color="success"
:loading="saveLoader"
#click="recordExpense()"
>save</v-btn
>
</v-flex>
</v-layout>
</v-card-text>
</v-card>
</v-dialog>
</template>
<script>
import NewUser from "#finance/libs/users/NewUser";
import {mapActions, mapGetters} from "vuex";
export default {
props: [
'queueId'
],
data: () => ({
dialog: false,
expense: new NewUser(),
saveLoader: false,
}),
computed: {
...mapGetters({
banks: "getBanks",
}),
balance: function () {
return parseFloat(10);
},
submitted() {
return this.expense.form.submitted;
},
contaminated() {
return this.expense.form.errorDetected;
},
errors() {
return this.expense.form.errors;
},
},
watch: {
submitted(v) {
if (v) {
this.saveLoader = false;
}
},
contaminated() {
this.saveLoader = false;
},
},
methods: {
...mapActions({
fetchBanks: "setBanks",
}),
setDoctor(user) {
this.expense.doctor_id = user.id;
},
setQueue(){
console.log(this.queueId);
this.expense.queueId = this.queueId;
},
async recordExpense() {
this.saveLoader = true;
let response = await this.expense.saveExpense();
this.saveLoader = false;
if (response) {
this.dialog = false;
this.$emit("expenseCreated");
}
},
},
mounted() {
this.fetchBanks();
}
};
</script>
The prop queueId i also want to store it along with the user information from the form.
Try this one, it should work:
<template>
<textarea v-model="hiddenValue" :style="{ display: 'none' }"></textarea>
</template>
<script>
export default {
props: [ 'queueId' ],
data() {
return {
hiddenValue: this.queueId
}
}
}
</script>
In case you will no need the prop to be modified, please bind the texarea value to the prop directly:
<textarea hidden v-model="queueId" :style="{ display: 'none' }></textarea>

How to programatically close a Veutify dialog

Hello everyone i was searching on the vuetify documentation a function or something like that to close a form dialog just after getting the axios response with the status 200 ..
i don't if there's a way to get a dialog instance and use a close() method on it like the bootstrap modals
here's my code :
template code
<template>
<v-dialog justify-center max-width="500px">
<template v-slot:activator="{on}">
<v-icon
small
v-on="on"
>
mdi-pencil
</v-icon>
</template>
<v-card>
<form #submit.prevent="submit">
<v-card-text>
<v-text-field
v-model="name"
label="Name"
required
></v-text-field>
<v-text-field
v-model="email"
label="E-mail"
required
></v-text-field>
<v-text-field
v-model="password"
label="password"
required>
</v-text-field>
</v-card-text>
<v-card-actions>
<v-btn
color="blue darken-1"
text
>close</v-btn>
<v-btn
color="blue darke-1"
text
type="submit"
>apply</v-btn>
</v-card-actions>
</form>
</v-card>
</v-dialog>
</template>
and here's the script
<script>
export default {
data () {
return {
name: '',
email: '',
password: ''
}
},
methods: {
submit() {
let Data = new FormData()
Data.append('name', this.name)
Data.append('email', this.email)
Data.append('password', this.password)
axios.post('http://stage.test/admin/users', Data)
.then(Response => {
if (Response.status === 200) {
}
})
}
},
}
</script>
Try to bind dialog component to a data property called open as follows :
<template>
<v-dialog v-model="open" justify-center max-width="500px">
<template v-slot:activator="{on}">
<v-icon
small
v-on="on"
>
mdi-pencil
</v-icon>
.....
then in then callback assign false to this.open
<script>
export default {
data () {
return {
open:false,
name: '',
email: '',
password: ''
}
},
methods: {
submit() {
let Data = new FormData()
Data.append('name', this.name)
Data.append('email', this.email)
Data.append('password', this.password)
axios.post('http://stage.test/admin/users', Data)
.then(Response => {
if (Response.status === 200) {
this.open=false
}
})
}
},
}
</script>

Vue, error [vuex] do not mutate vuex store state outside mutation handlers

Here is original code. Very simple, sign in form. We have Email field, password. It takes this parameters and on clicking submit button it checks the user and writes his user.uid into Vuex. But I'm getting error which is listed above in title. I did research and it looks like it's a common issue in Vuex, due to those fields at some point updating Vuex store 'on a fly' which is false in my case, cause it only updates Vuex store when you press a submit button. Anyhow decided corrected to be look like this and still have no luck
original code
<template>
<div class="form__inner">
<div class="overlay" #click="$store.commit('logReg/logIn')"></div>
<v-container
fill-height
fluid>
<v-row
align="center"
justify="center">
<v-col cols="2">
<v-card>
<v-card-title>
Log in
</v-card-title>
<v-card-text>
<v-text-field placeholder="Email"
v-model="logIn"/>
<v-text-field placeholder="Password"
v-model="password"/>
</v-card-text>
<v-card-actions>
<v-btn color="success"
class="mx-auto"
#click="signIn">Log me in</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</div>
</template>
<script>
export default {
data(){
return {
logIn: '',
password: ''
}
},
methods: {
async signIn(){
let res = await this.$fireAuth.signInWithEmailAndPassword(this.logIn, this.password);
this.$store.commit('userState', res);
}
}
}
</script>
my vuex
export const state = () => ({
user: null
})
export const mutations = {
userState(state, authUser){
state.user = authUser;
}
}
my try to fix issue which still had no luck, gives same error
<template>
<div class="form__inner">
<div class="overlay" #click="$store.commit('logReg/logIn')"></div>
<v-container
fill-height
fluid>
<v-row
align="center"
justify="center">
<v-col cols="2">
<v-card>
<v-card-title>
Log in
</v-card-title>
<v-card-text>
<v-text-field placeholder="Email"
v-model="logIn"/>
<v-text-field placeholder="Password"
v-model="password"/>
</v-card-text>
<v-card-actions>
<v-btn color="success"
class="mx-auto"
#click="signIn">Log me in</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</div>
</template>
<script>
export default {
data(){
return {
logIn: '',
password: ''
}
},
computed: {
logg: {
get(){
return this.logIn;
},
set(val){
this.logIn = val;
}
},
pass: {
get(){
return this.password;
},
set(val){
this.password = val;
}
}
},
methods: {
async signIn(){
let res = await this.$fireAuth.signInWithEmailAndPassword(this.logg, this.pass);
this.$store.commit('userState', res);
}
}
}
</script>
You have to use mutations like this:
<script>
import {mapMutations} from 'vuex';
export default {
data(){
return {
logIn: '',
password: ''
}
},
methods: {
...mapMutations({
userState: 'userState'
}),
async signIn(){
let res = await this.$fireAuth.signInWithEmailAndPassword(this.logIn,this.password);
this.userState(res);
}
}
}
</script>

How do I open and close v-dialog from a component under its parent? Use Vuex?

I need to open a CRUD dialog from a data table component. Both the dialog and data table share the same parent. The data table is reusable but the CRUD dialog is not.
The use case seems very common. An admin page contains a table of data, each row containing an edit button that opens edit dialog.
I've attempted using Vuex below - however this error occurs:
[Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'showUserModal' of undefined"
found in
---> <VBtn>
<VSimpleTable>
<VData>
<VDataTable>
<DataTable> at src/components/DataTable.vue
<Settings> at src/views/Settings.vue
<VContent>
<VApp>
<App> at src/App.vue
<Root>
Why is the imported mutator not available and is this a good approach to achieving the common functionality?
I arrived at my current solution using these 2 approaches
https://markus.oberlehner.net/blog/building-a-modal-dialog-with-vue-and-vuex/
https://forum.vuejs.org/t/how-to-trigger-a-modal-component-from-vuex-store/27243/9
UserAdmin.vue
<template>
<v-container fluid >
<DataTable v-bind:rows="allUsers" v-bind:headers="headers" />
<EditUser />
</v-container>
</template>
<script>
import { mapGetters, mapActions } from "vuex";
import DataTable from '../components/DataTable';
import EditUser from '../modals/EditUser';
export default {
name: 'UserAdmin',
methods: {
...mapActions(["getUsers"])
},
computed: mapGetters(["allUsers"]),
components: {
DataTable, EditUser
},
data(){
return {
headers: [
{ text: 'Name', value: 'name' },
{ text: 'Username', value: 'email' },
{ text: 'Administrator', value: 'admin' },
{ text: "", value: "controls", sortable: false}
]
}
},
created(){
this.getUsers();
}
}
</script>
DataTable.vue
<template>
<v-data-table
:headers="headers"
:items="rows"
:items-per-page="5"
class="elevation-1"
>
<!-- https://stackoverflow.com/questions/59081299/vuetify-insert-action-button-in-data-table-and-get-row-data -->
<template v-slot:item.controls="props">
<v-btn class="my-2" fab dark x-small color="blue" #click="onButtonClick(props.item.email)">
<v-icon dark>mdi-pencil</v-icon>
</v-btn>
</template>
</v-data-table>
</template>
<script>
import { mapMutations } from "vuex";
export default {
name: "DataTable",
props:["headers", "rows"],
methods: {
...mapMutations(["toggleUserModal"]),
onButtonClick: function(email) {
console.log("clicked: " + email)
this.toggleUserModal();
}
}
}
</script>
EditUser.vue
<template>
<v-row justify="center">
<v-dialog v-model="dialog" persistent max-width="600px" v-show='showUserModal'>
<v-card>
<v-card-title>
<span class="headline">User Profile</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="4">
<v-text-field label="Legal first name*" required></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field label="Legal middle name" hint="example of helper text only on focus"></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
label="Legal last name*"
hint="example of persistent helper text"
persistent-hint
required
></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field label="Email*" required></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field label="Password*" type="password" required></v-text-field>
</v-col>
<v-col cols="12" sm="6">
<v-select
:items="['0-17', '18-29', '30-54', '54+']"
label="Age*"
required
></v-select>
</v-col>
<v-col cols="12" sm="6">
<v-autocomplete
:items="['Skiing', 'Ice hockey', 'Soccer', 'Basketball', 'Hockey', 'Reading', 'Writing', 'Coding', 'Basejump']"
label="Interests"
multiple
></v-autocomplete>
</v-col>
</v-row>
</v-container>
<small>*indicates required field</small>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text #click="dialog = false">Close</v-btn>
<v-btn color="blue darken-1" text #click="dialog = false">Save</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
export default {
data: () => ({
dialog: false,
}),
computed: {
showUserModal(){
return this.$store.state.showUserModal
}
}
}
</script>
modals.js
const state = {
showUserModal: false
}
const mutations = {
toggleUserModal: () => (this.showUserModal = !this.showUserModal)
}
const getters = {
showUserModal: state => {
return state.showUserModal
}
}
export default {
state,
getters,
mutations
}
New code based on #Anatoly suggestions - everything works except the events emitted from the dialog, ex: onEditUserConfirmed are not picked up in the parent component.
ModalComponent
<template>
<v-row justify="center">
<v-dialog v-model="visible" persistent max-width="600px">
<v-card v-if="user">
<v-card-title>
<span class="headline">User Profile</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="4">
<v-text-field v-model="user.name" label="Legal first name*" required></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field label="Legal middle name" hint="example of helper text only on focus"></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
label="Legal last name*"
hint="example of persistent helper text"
persistent-hint
required
></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field label="Email*" required></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field label="Password*" type="password" required></v-text-field>
</v-col>
<v-col cols="12" sm="6">
<v-select :items="['0-17', '18-29', '30-54', '54+']" label="Age*" required></v-select>
</v-col>
<v-col cols="12" sm="6">
<v-autocomplete
:items="['Skiing', 'Ice hockey', 'Soccer', 'Basketball', 'Hockey', 'Reading', 'Writing', 'Coding', 'Basejump']"
label="Interests"
multiple
></v-autocomplete>
</v-col>
</v-row>
</v-container>
<small>*indicates required field</small>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text #click="onCancel">Close</v-btn>
<v-btn color="blue darken-1" text #click="onSave">Save</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
export default {
name: "EditUser",
props: {
user: Object,
visible: {
type: Boolean,
default: false
}
},
methods: {
onSave() {
console.log('save button gets here...')
this.$emit("onEditUserConfirmed", this.user);
},
onCancel() {
console.log('cancel button gets here...')
this.$emit("onEditUserCancelled");
}
}
};
</script>
Parent Component
<template>
<v-container fluid>
<v-data-table :headers="headers" :items="allUsers" :items-per-page="5" class="elevation-1">
<!-- https://stackoverflow.com/questions/59081299/vuetify-insert-action-button-in-data-table-and-get-row-data -->
<template v-slot:item.controls="props">
<v-btn class="my-2" fab dark x-small color="blue" #click="onEditClick(props.item)">
<v-icon dark>mdi-pencil</v-icon>
</v-btn>
</template>
</v-data-table>
<EditUser
:user="user"
:visible="isDialogVisible"
#confirmed="onEditUserConfirmed"
#cancelled="onEditUserCancelled"
/>
</v-container>
</template>
<script>
import { mapGetters, mapActions } from "vuex";
import EditUser from "../modals/EditUser";
export default {
name: "Settings",
data() {
return {
user: null,
isDialogVisible: false,
headers: [
{ text: "Name", value: "name" },
{ text: "Username", value: "email" },
{ text: "Administrator", value: "admin" },
{ text: "", value: "controls", sortable: false }
]
};
},
methods: {
...mapActions(["getUsers"]),
onEditClick: function(user) {
console.log('Editing user: ' + user.email)
this.user = user;
this.isDialogVisible = true;
},
onEditUserConfirmed(user) {
console.log('Saving user: ' + user.email)
this.isDialogVisible = false;
},
onEditUserCancelled () {
this.isDialogVisible = false;
}
},
computed: mapGetters(["allUsers"]),
components: {
EditUser
},
created() {
this.getUsers();
}
};
</script>
I would not recommend using the state for this task. since it not a very complex scenarios. you should use props and events for handling this kind of scenario
just modify the code a bit.
DataTable.vue
<script>
methods: {
onButtonClick: function(email) {
console.log("clicked: " + email)
this.$emit('openDialog') // or use any name here
}
}
</script>
UserAdmin.vue
<template>
<v-container fluid >
<!-- Listen to the event that you are emitting from DataTable.vue -->
<DataTable :rows="allUsers" :headers="headers" #showDialog="editUser = true" />
<!-- Pass that variable as a Prop -->
<EditUser :showDialog="editUser" />
</v-container>
</template>
<script>
....
data: () => ({
headers: [
{ text: 'Name', value: 'name' },
{ text: 'Username', value: 'email' },
{ text: 'Administrator', value: 'admin' },
{ text: "", value: "controls", sortable: false}
],
editUser: false, // a flag to keep the status of modal.
})
....
</script>
EditUser.vue
<script>
export default {
props: {
showDialog: {
type: Boolean,
default: false
}
},
data: () => ({
dialog: false,
}),
mounted() {
this.dialog = this.showDialog
},
watch: {
showDialog() {
if (this.showDialog)
this.dialog = true
}
}
}
</script>
I hope it should work, it worked for me in my scenario. I won't recommend using the Vuex store in this simple single level structure. Vuex should be used in case of some complex data structures where there are deep layers of components.
The code might have some syntax mistakes (do let me know). but i hope i just conveyed the concept
Use an event in a table component to inform a parent component you wish to edit a user (send a selected user in this event).
Catch the event in a parent component, write a user from the event to a prop in data section and pass this prop to a dialog component.
Use a prop to show/hide dialog from a parent component
Use an event to receive edited user after dialog confirmation.
Something like this:
Parent component
<DataTable v-bind:rows="allUsers" v-bind:headers="headers" #onEdit="onEditUser"/>
<EditUser :user="user" :visible="isDialogVisible" #confirmed="onEditUserConfirmed" #cancelled="onEditUserCancelled"/>
...
data: {
return {
// other data
user: null,
isDialogVisible : false
}
},
methods: {
onEditUser (user) {
this.user = user
this.isDialogVisible = true
},
onEditUserConfirmed (user) {
// hide a dialog
this.isDialogVisible = false
// save a user and refresh a table
},
onEditUserCancelled () {
// hide a dialog
this.isDialogVisible = false
}
}
Table component:
// better send a whole user object insteaf of just e-mail prop? It's up to you
#click="onButtonClick(props.item)"
...
methods: {
onButtonClick: function(user) {
this.$emit('onEdit', user)
}
}
Dialog component:
<v-dialog v-model="visible" ...
// render card only if user is passed
<v-card v-if="user">
<v-col cols="12" sm="6" md="4">
<v-text-field v-model="user.firstName" label="Legal first name*" required></v-text-field>
</v-col>
...
<v-btn color="blue darken-1" text #click="onCancel">Close</v-btn>
<v-btn color="blue darken-1" text #click="onSave">Save</v-btn>
...
export default {
props: {
user: {
type: Object
},
visible: {
type: Boolean,
default: false
}
},
...
methods: {
onSave() {
this.$emit('confirmed', this.user)
},
onCancel () {
this.$emit('cancelled')
}
}
}

Get Current User Login User Information in Profile Page - Firebase and Vuejs

I'm trying to create a user profile for signed up users in my application.
I created a collection named profiles and field name in my cloud firestore to store the user's name when they register for an account.
So, I'm using vuex for better management. Here is a piece of code for what I've done so far.
My Store.js
signUserUp ({commit}, payload) {
commit('setLoading', true)
commit('clearError')
firebase.auth().createUserWithEmailAndPassword(payload.email, payload.password)
.then(
user => {
commit('setLoading', false)
const newUser = {
id: user.uid
}
commit('setUser', newUser)
// Add a new document in collection "cities"
db.collection('profiles').doc(user.user.uid).set({
name: payload.name
})
.then(function () {
console.log('Document successfully written!')
})
.catch(function (error) {
console.error('Error writing document: ', error)
})
toastr.success('Your Account was created successfully')
}
)
.catch(
error => {
commit('setLoading', false)
commit('setError', error)
toastr.error('Oops' + error.message)
}
)
}
My SignUp.vue
This is my text field to collect the user name first followed by the email and password of the user.
<form #submit.prevent="onSignup">
<v-layout row>
<v-flex xs12>
<v-text-field
name="name"
label="Name"
id="name"
v-model="name"
type="text"
required></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<v-text-field
name="email"
label="Email"
id="email"
v-model="email"
type="email"
required></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<v-text-field
:append-icon="showPassword ? 'visibility' : 'visibility_off'"
:type="showPassword ? 'text' : 'password'"
name="password input-10-2"
label="Password"
id="password"
value=""
class="input-group--focused"
v-model="password"
#click:append="showPassword = !showPassword"
required
></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<v-text-field
:append-icon="showPasswordConfirm ? 'visibility' : 'visibility_off'"
:type="showPasswordConfirm ? 'text' : 'password'"
name="confirmPassword input-10-2"
label="Confirm Password"
id="confirmPassword"
value=""
class="input-group--focused"
v-model="confirmPassword"
#click:append="showPasswordConfirm = !showPasswordConfirm"
:rules="[comparePasswords]"
></v-text-field>
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs12 sm6 class="text-xs-center text-sm-left">
<v-btn
color="#4527a0"
type="submit"
class="btn__content"
:loading="loading"
:disabled="loading"
#click="loader = 'loading'"
>
Sign up
<span slot="loader" class="custom-loader">
<v-icon light>cached</v-icon>
</span>
</v-btn>
</v-flex>
<v-flex xs12 sm6 class="mt-3 text-xs-center text-sm-right">
<router-link to="/signin" tag="span" style="cursor: pointer;">Already have an Account? Sign in</router-link>
</v-flex>
</v-layout>
</form>
The script for my SignUp.vue
export default {
data () {
return {
name: null,
email: null,
password: '',
confirmPassword: '',
showPassword: false,
showPasswordConfirm: false,
loader: null
}
},
methods: {
onSignup () {
this.$store.dispatch('signUserUp', {email: this.email, password: this.password})
}
}
I want the name the user enters during signing up for an account being pushed to the field I've in the profiles collection. But I'm getting this error
DocumentReference.set() called with invalid data. Unsupported field value: undefined (found in field name)
In your code, you are using
firebase.auth().createUserWithEmailAndPassword(payload.email, payload.password).then(user=>{
//getting your user details
});
But there is no any
then(user=>{//user details})
function in firebase to get user detail after sign up or log in.
There is a separate function to check the authentication state of a user where you can get your user detail and then store it is Firestore.
You can use the following method:-
For Signup of a user:
firebase.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
After signup you have to signIn your user to get user detail in authentication observer.
For SignIn of a user:
firebase.auth().signInWithEmailAndPassword(email, password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
When a user successfully signs in, you can get information about the user in the observer.
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
var displayName = user.displayName;
var email = user.email;
var emailVerified = user.emailVerified;
var photoURL = user.photoURL;
var isAnonymous = user.isAnonymous;
var uid = user.uid;
var providerData = user.providerData;
// ...
} else {
// User is signed out.
// ...
}
});