J'ai suivi ce tutoriel pour essayer d'apprendre Vue, j'ai terminé et ça fonctionne, mais j'essaie de faire un changement avec lequel j'ai du mal.
https://savvyapps.com/blog/definitive-guide-building-web-app-vuejs-firebase
Il y a donc une page "paramètres" qui contient le profil de l'utilisateur (il peut modifier son nom, etc.). Lorsque cette page "paramètres" / "profil" est chargée, je veux que le formulaire charge les données existantes afin que l'utilisateur puisse les modifier et cliquer sur "enregistrer".
Il se charge actuellement comme un espace réservé avec :placeholder="userProfile.name"
- Je veux qu'il remplisse le formulaire avec la valeur réelle au lieu de l'avoir en tant qu'espace réservé.
J'ai l'impression que cela devrait être ridiculement simple à faire, mais je n'arrive pas à le faire fonctionner de manière élégante.
Settings.vue
<template>
<section id="settings">
<div class="col1">
<h3>Settings</h3>
<p>Update your profile</p>
<transition name="fade">
<p v-if="showSuccess" class="success">profile updated</p>
</transition>
<form @submit.prevent>
<label for="name">Name</label>
<input v-model.trim="name" type="text" id="name" />
<label for="title">Job Title</label>
<input v-model.trim="title" type="text" id="title" />
<button @click="updateProfile()" class="button">Update Profile</button>
</form>
</div>
</section>
</template>
<script>
import { mapState } from "vuex";
export default {
data() {
return {
name: "",
title: "",
showSuccess: false,
};
},
computed: {
...mapState(["userProfile"]),
},
methods: {
updateProfile() {
this.$store.dispatch("updateProfile", {
name: this.name !== "" ? this.name : this.userProfile.name,
title: this.title !== "" ? this.title : this.userProfile.title,
});
this.name = "";
this.title = "";
this.showSuccess = true;
setTimeout(() => {
this.showSuccess = false;
}, 2000);
},
},
};
</script>
<style lang="scss" scoped>
</style>
J'ai essayé de modifier la section des données comme suit, ce qui fonctionne lorsque je quitte la page et que j'y reviens, mais si je rafraîchis la page (F5), les champs restent vides jusqu'à ce que je quitte la page et que j'y revienne.
data() {
return {
name: this.$store.state.userProfile.name,
title: this.$store.state.userProfile.title,
showSuccess: false,
};
},
Et voici mon magasin si vous avez besoin de le voir :
store/index.js
import Vue from "vue";
import Vuex from "vuex";
import * as fb from "../firebase";
import router from "../router/index";
Vue.use(Vuex);
// realtime firebase connection
fb.postsCollection.orderBy("createdOn", "desc").onSnapshot((snapshot) => {
let postsArray = [];
snapshot.forEach((doc) => {
let post = doc.data();
post.id = doc.id;
postsArray.push(post);
});
store.commit("setPosts", postsArray);
});
const store = new Vuex.Store({
state: {
userProfile: {},
posts: [],
},
mutations: {
setUserProfile(state, val) {
state.userProfile = val;
},
setPosts(state, val) {
state.posts = val;
},
},
actions: {
async signup({ dispatch }, form) {
// sign user up
const { user } = await fb.auth.createUserWithEmailAndPassword(
form.email,
form.password
);
// create user profile object in userCollections
await fb.usersCollection.doc(user.uid).set({
name: form.name,
title: form.title,
});
// fetch user profile and set in state
dispatch("fetchUserProfile", user);
},
async login({ dispatch }, form) {
// sign user in
const { user } = await fb.auth.signInWithEmailAndPassword(
form.email,
form.password
);
// fetch user profile and set in state
dispatch("fetchUserProfile", user);
},
async logout({ commit }) {
await fb.auth.signOut();
// clear userProfile and redirect to /login
commit("setUserProfile", {});
router.push("/login");
},
async fetchUserProfile({ commit }, user) {
// fetch user profile
const userProfile = await fb.usersCollection.doc(user.uid).get();
// set user profile in state
commit("setUserProfile", userProfile.data());
// change route to dashboard
if (router.currentRoute.path === "/login") {
router.push("/");
}
},
async createPost({ state }, post) {
await fb.postsCollection.add({
createdOn: new Date(),
content: post.content,
userId: fb.auth.currentUser.uid,
userName: state.userProfile.name,
comments: 0,
likes: 0,
});
},
async likePost(context, { id, likesCount }) {
const userId = fb.auth.currentUser.uid;
const docId = `${userId}_${id}`;
// check if user has liked post
const doc = await fb.likesCollection.doc(docId).get();
if (doc.exists) {
return;
}
// create post
await fb.likesCollection.doc(docId).set({
postId: id,
userId: userId,
});
// update post likes count
fb.postsCollection.doc(id).update({
likes: likesCount + 1,
});
},
async updateProfile({ dispatch }, user) {
const userId = fb.auth.currentUser.uid;
// update user object
/*const userRef = */await fb.usersCollection.doc(userId).update({
name: user.name,
title: user.title,
});
dispatch("fetchUserProfile", { uid: userId });
// update all posts by user
const postDocs = await fb.postsCollection
.where("userId", "==", userId)
.get();
postDocs.forEach((doc) => {
fb.postsCollection.doc(doc.id).update({
userName: user.name,
});
});
// update all comments by user
const commentDocs = await fb.commentsCollection
.where("userId", "==", userId)
.get();
commentDocs.forEach((doc) => {
fb.commentsCollection.doc(doc.id).update({
userName: user.name,
});
});
},
},
modules: {},
});
export default store;
EDIT
J'aurais dû mentionner que ces données sont chargées dans l'état à partir d'un Firebase Firestore. Il semble que ce soit juste un problème de timing, les données ne sont pas tout à fait chargées au moment où il met en place le data() sur le composant - j'ai ajouté quelques logs de console.
Fetching user profile.. Settings.vue?e12e:29
Setting Data... index.js?4360:75
Performing setUserProfile commit.. index.js?4360:29
Setting user profile in state, last step..
Encore une fois, je ne connais pas assez Vue pour savoir comment modifier au mieux cet ordre