Utilizing Vue.js for Streamlined Form Management: Adding and Editing with One Form

I'm attempting to utilize the same component for both adding and editing functionality in my application. Utilizing Firebase, I am checking if there is an id in the route parameters. If there is, it should render as the edit form; otherwise, it should render the add form. However, this approach is not functioning correctly and displaying some odd behavior.

Below is the code for the ContactForm component:

<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 {
  components: {
    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

Answer №1

Upon duplicating the repository, I proceeded with localized testing and integrated alterations to facilitate utilizing a singular form for both editing and adding purposes.

The adjustments to the code are outlined below for specific files. Simply copy and paste the provided code into the designated files:

src/components/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>

...

src/components/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>
      </h4>
      <ul class="list-group" v-if="showContactInfo">
        <li class="list-group-item">Email: {{ contact.email }}</li>
         ...
      </ul>
    </div>
  </div>
</template>

...

src/components/layout/Navbar.vue

<template>
  <div>
    <nav class="navbar navbar-expand-sm navbar-dark bg-danger mb-3 py-0">
      
      ...
        
    </nav>
  </div>
</template>

...

src/views/ContactForm.vue

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

...

</script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for retrieving data from a JSON response with the specified structure

When I make a request, the response is as follows: { "data": [ "http:\/\/www.domain.com.br\/anunciantes\/jorgediaz.y.com.r\/26\/img1.jpg", "http:\/\/www.domain.com.br\/anunciantes\/jorg ...

Automatically generate the first user on the Parse Server system

Is it feasible to programmatically create a User on Parse server without the need for sign up? More information can be found at https://github.com/parse-community/parse-server We attempted this using cloud code. var user = Parse.User(); user.setUserna ...

Retrieving values from all fields in a dynamic form using VuejsLet's say

In the process of developing an admin panel using Vuejs and tailwind CSS for managing exercises on a page, I have encountered some challenges. My current objective is to insert the dynamic form values into a Firebase real-time database. However, I am stru ...

Is there a way for me to verify the type of these objects?

Could you help me verify the type of obj below? Question 1: const arr = ["a", "b", "c"] is equivalent to arr = { 0: "a", 1: "b", 2: "c" } Is this correct? Question 2: My object is const myObjects = { "1111": { isField: true, mySet: [" ...

Tips for displaying an arrow icon that points up or down when clicking on a table header in Vue.js

I am currently working on a listing page where data is fetched using Laravel. The issue I am facing is related to sorting functionality when clicking on the table headings (<th>). The desired behavior is for arrow marks to indicate ascending or desce ...

The Quasar Icon Genie CLI transforms square icons into rectangle shapes

Is there a way to prevent cropping when generating icons for my Capacitor app using Icon Genie CLI? I have a 512x512 icon that I am passing to the tool, but the resulting icons are cropped to a rectangle and have a white background on iOS. Here is an examp ...

JavaScript pause until the DOM has been modified

My current situation involves using a JavaScript file to make changes to the DOM of a page by adding a navigation menu. Following this code, there is another function that further modifies the newly added navigation menu. However, I am facing an issue wher ...

What is the most effective method to determine if a given string is suitable for $compile in Angular?

I am currently in the process of creating a directive that is designed to accept a "message" input which may contain HTML and nested Angular directives. In my directive's controller, I am using the following code: var compiled = $compile(message)($sc ...

Avoiding Dropdown Click Propagation in Bootstrap and AngularJS

When using Bootstrap 3 and AngularJS, I have a list group where each item has a dropdown menu aligned to the right. I want it so that when I click on the dropdown, only the dropdown menu is displayed without triggering the "itemSelected" function for the i ...

Exploring Object Elements using For Loop

After trying numerous methods, I am still puzzled by this issue. I have a feeling that the solution is going to be something very simple, but nevertheless, I need to ask for help. This is the function I'm dealing with: Module.load = function(a) { ...

Having trouble testing a basic Vue example component in Laravel 5.4

I recently installed Laravel 5.4 and after running npm install, I tested a vue component example but nothing happened as expected. After running npm run dev in my project directory, the compilation was successful. However, when I ran php artisan serve, al ...

Tips for accessing the value of a specific key within an object that is nested in an array

I'm attempting to extract the name of the merchant from within this specific array: [ { "model": "inventory.merchant", "pk": 1, "fields": { "merchant_name": "Gadgets R Us", "joined": "2020-01-06T07:16:17.365Z" } }, ...

How come pagination links in Vue.js 2 return JSON when clicked?

My question relates to having 2 specific components: Firstly, there is a component called SearchResultVue.vue. The structure of this component is as follows : <template> ... <span class="pull-right" v-show="totalall>8"> ...

Dynamic resizing of grids using React and TypeScript

I'm attempting to create a dynamic grid resizing functionality in React and TypeScript by adjusting the lgEditorSize value on onClick action. Setting the initial lgEditorSize value const size: any = {}; size.lgEditorSize = 6; Adjusting the lgEditorS ...

What is the process for sending a request to Electron from my backend using NAPI?

I'm currently working on a project using Electron, and I have a NAPI file that contains my backend code. In my user interface, when a specific button is clicked, it triggers a function that calls the function from NAPI. Electron acts as the bridge bet ...

innerHTML not showing up on the page

Trying to implement a dynamic navbar that changes based on whether a user is signed in or not. The authentication part is functioning correctly (verified with console logs); however, there seems to be an issue with updating the HTML using .innerHTML = ... ...

Allow for the ability to choose a specific option for every individual line that is echoed in

I have researched several similar questions, but none of them address exactly what I am attempting to achieve. My goal is to use AJAX to fetch a PHP page that will display the contents of a folder on my server. Currently, the files are being listed line by ...

Issues encountered when using PUT requests in a react.js application

I've encountered an issue with a PUT request where, after editing one field and saving, all other values except the edited one become null. It seems to be related to the onChange() function, but I'm not entirely sure. Below is all the relevant co ...

Verify if the user has admin privileges using Vue Router and Vuex

I am currently developing an application which features an admin section. Users are categorized as either admin or non-admin in the database by: admin = 1 The data is fetched using axios and then the user's state is set using vuex. However, I am fac ...

Empty Media Viewer

I am encountering an issue with setting up a code, as it only displays a blank white page. Any suggestions on what might be causing this problem in the setup and assistance in resolving it would be greatly appreciated. <script type="text/javascript ...