javascript - Vuejs - How to use a single form to add and edit - Stack Overflow

I'm trying to use the same ponent to handle the Add and Edit part of my app. I'm using Fireba

I'm trying to use the same ponent to handle the Add and Edit part of my app. I'm using Firebase, so I'm checking if there is an id in the route params, if there is, it renders as the edit form, if not, renders as the add form. But this doesn't work and it has some wierd behaviour.

Here is the code for the ContactForm ponent

<template>
  <div>
    <div class="card mb-3">
      <div class="card-header">{{ editing ? 'Edit' : 'Add' }} Contact</div>
      <div class="card-body">
        <form @submit.prevent="addContact">
          <TextInputGroup
            label="Name"
            name="name"
            placeholder="Enter your name..."
            v-model="contact.name"
            for="name"
          />
          <TextInputGroup
            type="email"
            label="Email"
            name="email"
            placeholder="Enter your email..."
            v-model="contact.email"
          />
          <TextInputGroup
            type="phone"
            label="Phone"
            name="phone"
            placeholder="Enter your phone number..."
            v-model="contact.phone"
          />

          <input type="submit" value="Add Contact" class="btn btn-block btn-light" />
        </form>
      </div>
    </div>
  </div>
</template>

<script>
import TextInputGroup from "../layout/TextInputGroup";
import { db } from "../../firebase";

export default {
  ponents: {
    TextInputGroup
  },
  data() {
    return {
      contact: "",
      editing: false,
      email: "",
      name: "",
      phone: ""
    };
  },
  methods: {
    addContact() {
      const newContact = {
        name: this.name,
        email: this.email,
        phone: this.phone,
        createdAt: new Date()
      };
      db.collection("contacts")
        .add(newContact)
        .then(docRef => {
          console.log("Document written with ID: ", docRef.id);
        })
        .catch(error => {
          console.error("Error adding document: ", error);
        });
      this.$router.push("/");
    },
    getContactById() {
      db.collection("contacts")
        .doc(this.$route.params.id)
        .get()
        .then(snapshot => {
          if (!snapshot.exists) return;
          this.contact = snapshot.data();
        });
    },
    updateContact() {
      const newContact = {
        name: this.contact.name,
        email: this.contact.email,
        phone: this.contact.phone
      };
      db.collection("contacts")
        .doc(this.$route.params.id)
        .update(newContact)
        .then(() => {
          console.log("Updated document with ID: ");
        })
        .catch(function(error) {
          console.error("Error updating document: ", error);
        });
      this.$router.push("/");
    }
  },
  mounted() {
    if ("id" in this.$route.params) {
      this.getContactById();
      this.editing = true;
      console.log("id");
    } else {
      console.log("ups");
      // this
    }
  }
};
</script>

This is the github link and the live app

I'm trying to use the same ponent to handle the Add and Edit part of my app. I'm using Firebase, so I'm checking if there is an id in the route params, if there is, it renders as the edit form, if not, renders as the add form. But this doesn't work and it has some wierd behaviour.

Here is the code for the ContactForm ponent

<template>
  <div>
    <div class="card mb-3">
      <div class="card-header">{{ editing ? 'Edit' : 'Add' }} Contact</div>
      <div class="card-body">
        <form @submit.prevent="addContact">
          <TextInputGroup
            label="Name"
            name="name"
            placeholder="Enter your name..."
            v-model="contact.name"
            for="name"
          />
          <TextInputGroup
            type="email"
            label="Email"
            name="email"
            placeholder="Enter your email..."
            v-model="contact.email"
          />
          <TextInputGroup
            type="phone"
            label="Phone"
            name="phone"
            placeholder="Enter your phone number..."
            v-model="contact.phone"
          />

          <input type="submit" value="Add Contact" class="btn btn-block btn-light" />
        </form>
      </div>
    </div>
  </div>
</template>

<script>
import TextInputGroup from "../layout/TextInputGroup";
import { db } from "../../firebase";

export default {
  ponents: {
    TextInputGroup
  },
  data() {
    return {
      contact: "",
      editing: false,
      email: "",
      name: "",
      phone: ""
    };
  },
  methods: {
    addContact() {
      const newContact = {
        name: this.name,
        email: this.email,
        phone: this.phone,
        createdAt: new Date()
      };
      db.collection("contacts")
        .add(newContact)
        .then(docRef => {
          console.log("Document written with ID: ", docRef.id);
        })
        .catch(error => {
          console.error("Error adding document: ", error);
        });
      this.$router.push("/");
    },
    getContactById() {
      db.collection("contacts")
        .doc(this.$route.params.id)
        .get()
        .then(snapshot => {
          if (!snapshot.exists) return;
          this.contact = snapshot.data();
        });
    },
    updateContact() {
      const newContact = {
        name: this.contact.name,
        email: this.contact.email,
        phone: this.contact.phone
      };
      db.collection("contacts")
        .doc(this.$route.params.id)
        .update(newContact)
        .then(() => {
          console.log("Updated document with ID: ");
        })
        .catch(function(error) {
          console.error("Error updating document: ", error);
        });
      this.$router.push("/");
    }
  },
  mounted() {
    if ("id" in this.$route.params) {
      this.getContactById();
      this.editing = true;
      console.log("id");
    } else {
      console.log("ups");
      // this
    }
  }
};
</script>

This is the github link and the live app

Share Improve this question edited Dec 7, 2020 at 10:16 Serhiy 4,1413 gold badges38 silver badges66 bronze badges asked Oct 24, 2019 at 19:29 PeorayPeoray 1,9253 gold badges15 silver badges24 bronze badges 9
  • Any error message in the console? – Renaud Tarnec Commented Oct 24, 2019 at 20:02
  • no...there is nothing – Peoray Commented Oct 24, 2019 at 20:09
  • And what if you only keep the created hook? I don't think it will change anything but just trying anything that can be tried.... – Renaud Tarnec Commented Oct 24, 2019 at 20:10
  • I don't understand, can you explain further? – Peoray Commented Oct 24, 2019 at 20:13
  • You are sure there is data in your contact collection and there is no security rule that prevent reading the data? – Renaud Tarnec Commented Oct 24, 2019 at 20:13
 |  Show 4 more ments

1 Answer 1

Reset to default 5

I just cloned you repository and tested in local, Added fixes to use single form for editing and adding

Here is the code for following files, just copy paste this code in below mentioned files

src/ponents/contact/ContactForm.vue

<template>
  <div>
    <div class="card mb-3">
      <div class="card-header">{{ editing ? 'Edit' : 'Add' }} Contact</div>
      <div class="card-body">
        <form @submit.prevent="addContact">
          <TextInputGroup
            label="Name"
            name="name"
            placeholder="Enter your name..."
            v-model="contact.name"
            for="name"
          />
          <TextInputGroup
            type="email"
            label="Email"
            name="email"
            placeholder="Enter your email..."
            v-model="contact.email"
          />
          <TextInputGroup
            type="phone"
            label="Phone"
            name="phone"
            placeholder="Enter your phone number..."
            v-model="contact.phone"
          />

          <input type="submit" value="Add Contact" class="btn btn-block btn-light" />
        </form>
      </div>
    </div>
  </div>
</template>

<script>
import TextInputGroup from "../layout/TextInputGroup";
import { db } from "../../firebase";

var temp = Object.freeze({
      name: '',
      email: '',
      phone: '',
    });

export default {
  ponents: {
    TextInputGroup
  },
  props: {
    type: {
      type: String,
      default: '',
    },
  },
  data() {
    

    return {
      contact: Object.assign({}, temp),
      editing: false,
    };
  },
  methods: {
    addContact() {
      this.contact.createdAt = new Date();
      db.collection("contacts")
        .add(this.contact)
        .then(docRef => {
          console.log("Document written with ID: ", docRef.id);
        })
        .catch(error => {
          console.error("Error adding document: ", error);
        });
      this.$router.push("/");
    },
    getContactById() {
      db.collection("contacts")
        .doc(this.$route.params.id)
        .get()
        .then(snapshot => {
          if (!snapshot.exists) return;
          this.contact = snapshot.data();
        });
    },
    updateContact() {
      db.collection("contacts")
        .doc(this.$route.params.id)
        .update(this.contact)
        .then(() => {
          console.log("Updated document with ID: ");
        })
        .catch(function(error) {
          console.error("Error updating document: ", error);
        });
      this.$router.push("/");
    }
  },
  created() {
    if ("id" in this.$route.params) {
      this.getContactById();
      this.editing = true;
      console.log("id");
    } else {
      console.log("ups");
      // this
    }
  },
  watch: {
    type(val) {
      if (val == 'add') {
        this.contact = Object.assign({}, temp);
      }
    }
  }
};
</script>

src/ponents/contact/ContactItem.vue

<template>
  <div>
    <div class="card card-body mb-3">
      <h4>
        {{ contact.name }}
        <i
          class="fas fa-sort-down pointer"
          @click="showContactInfo = !showContactInfo"
        ></i>
        <i class="fas fa-times delete right delete" @click="deleteContact(contact.id)"></i>
        <router-link :to="{path: `contact/edit/${contact.id}`, params: { id: contact.id }, query: { type: 'edit' }}">
          <i class="fas fa-pencil-alt edit right"></i>
        </router-link>
      </h4>
      <ul class="list-group" v-if="showContactInfo">
        <li class="list-group-item">Email: {{ contact.email }}</li>
        <li class="list-group-item">Phone: {{ contact.phone }}</li>
      </ul>
    </div>
  </div>
</template>

<script>
import { db } from "../../firebase";

export default {
  props: {
    contact: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      showContactInfo: false
    };
  },
  methods: {
    deleteContact(id) {
      db.collection("contacts")
        .doc(id)
        .delete()
        .then(function() {
          console.log("Document successfully deleted!");
        })
        .catch(function(error) {
          console.error("Error removing document: ", error);
        });
    }
  }
};
</script>

<style scoped>
.pointer {
  cursor: pointer;
}
.right {
  cursor: pointer;
  float: right;
}

.edit {
  color: black;
  margin-right: 1rem;
}

.delete {
  color: red;
}
</style>

src/ponents/layout/Navbar.vue

<template>
  <div>
    <nav class="navbar navbar-expand-sm navbar-dark bg-danger mb-3 py-0">
      <div class="container">
        <a href="/" class="navbar-brand">Contact Manager</a>
        <div>
          <ul class="navbar-nav mr-auto">
            <li class="nav-item">
              <router-link to="/" class="nav-link">
                <i class="fas fa-home" />
                Home
              </router-link>
            </li>
            <li class="nav-item">
              <router-link :to="{ path: '/contact/add', query: { type: 'add' } }" class="nav-link">
                <i class="fas fa-plus" />
                Add
              </router-link>
            </li>
            <li class="nav-item">
              <router-link to="/about" class="nav-link">
                <i class="fas fa-question" />
                About
              </router-link>
            </li>
          </ul>
        </div>
      </div>
    </nav>
  </div>
</template>

src/views/ContactForm.vue

<template>
  <ContactForm :type="formType" />
</template>

<script>
// @ is an alias to /src
import ContactForm from "@/ponents/contact/ContactForm.vue";

export default {
  name: "home",
  data() {
    return {
      formType: '',
    };
  },
  ponents: {
    ContactForm
  },
  watch: { 
   '$route.query.type': {
      handler: function(type) {
        this.formType = type;
      },
      deep: true,
      immediate: true
    }
  }
};
</script>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742345987a4426551.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信