Vue.js versatile form for both adding and editing

As a newcomer to the world of vue.js, I am currently working on expanding some tutorials that I have completed. After struggling with this for three hours now, I must admit that I am feeling quite frustrated. Just to give you a heads up, I am using firebase, although I am not entirely sure if that information is relevant in this context.

So, here's what I have: a basic CRUD app for listing movies. There is a form at the top of the page where users can add movies, and below it, there is a table displaying the newly added entries. So far, everything seems to be functioning smoothly.

I recently introduced Edit and Delete buttons to each row on the table. While the delete function is working as expected, I am encountering an issue with the Edit function.

The main challenge lies in my attempt to use v-if on the initial form in order to trigger different methods (such as save and edit) and display different buttons (Add, Save, Cancel).

I've been experimenting with various approaches to access the objects required for this operation, but unfortunately, I keep running into errors where the object is deemed undefined by v-if.

Thank you for taking the time to read this. Please feel free to ask any questions if you require further clarification or details.

import './firebase' // storing credentials and initializing firebase
import Vue from 'vue'
import App from './App'
import VueFire from 'vuefire'

Vue.use(VueFire)
Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
})
<template>
  <div id="app" class="container">
    <div class="page-header">
      <h1>Vue Movies</h1>
    </div>
 
    <div class="panel panel-default">
      <div class="panel-heading">
        <h3>Add Movie</h3>
      </div>
 
      <div class="panel-body">

        <div v-if="!isEditing">
          <form id="form" class="form-inline" v-on:submit.prevent="addMovie">
            <div class="form-group">
              <label for="movieTitle">Title:</label>
              <input type="text" id="movieTitle" class="form-control" v-model="newMovie.title">
            </div>
            <div class="form-group">
              <label for="movieDirector">Director:</label>
              <input type="text" id="movieDirector" class="form-control" v-model="newMovie.director">
            </div>
            <div class="form-group">
              <label for="movieUrl">URL:</label>
              <input type="text" id="movieUrl" class="form-control" v-model="newMovie.url">
            </div>
            <input type="submit" class="btn btn-primary" value="Add Movie">
          </form>
        </div>

        <div v-else>
          <form id="form" class="form-inline" v-on:submit.prevent="saveEdit(movie)">
            <div class="form-group">
              <label for="movieTitle">Title:</label>
              <input type="text" id="movieTitle" class="form-control" v-model="movie.title">
            </div>
            <div class="form-group">
              <label for="movieDirector">Director:</label>
              <input type="text" id="movieDirector" class="form-control" v-model="movie.director">
            </div>
            <div class="form-group">
              <label for="movieUrl">URL:</label>
              <input type="text" id="movieUrl" class="form-control" v-model="movie.url">
            </div>
            <input type="submit" class="btn btn-primary" value="Save">
            <button v-on:click="cancelEdit(movie['.key'])">Cancel</button>
          </form>
        </div>

      </div>

    </div>
 
    <div class="panel panel-default">
      <div class="panel-heading">
        <h3>Movies List</h3>
      </div>
      <div class="panel-body">
        <table class="table table-stripped">
          <thead>
            <tr>
              <th>Title</th>
              <th>director</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="movie in movies">

              <td>
                <a v-bind:href="movie.url" v-bind:key="movie['.key']" target="_blank">{{movie.title}}</a>
              </td>
              <td>
                {{movie.director}}
              </td>
              <td>
                <button v-on:click="editMovie(movie)">Edit</button>
              </td>
              <td>
                <button v-on:click="removeMovie(movie)">Remove</button>
              </td>

            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</template>

<script>

import { moviesRef } from './firebase'

export default {
  name: 'app',
  firebase: {
    movies: moviesRef
  },
  data () {
    return {
      isEditing: false, // could this potentially help?
      newMovie: {
        title: '',
        director: '',
        url: 'http://',
        edit: false // perhaps this??
      }
    }
  },
  methods: {
    addMovie: function() {
      moviesRef.push( this.newMovie )
      this.newMovie.title = '',
      this.newMovie.director = '',
      this.newMovie.url = 'http://'
      this.newMovie.edit = false
    },
    editMovie: function (movie){
      moviesRef.child(movie['.key']).update({ edit:true }); // struggling with accessing this particular section using v-if, unclear why
      //this.newMovie = movie;
    },
    removeMovie: function (movie) {
      moviesRef.child(movie['.key']).remove()
    },
    cancelEdit(key){
      moviesRef.child(key).update({ edit:false })
    },
    saveEdit(movie){
      const key = movie['key'];
      moviesRef.child(key).set({
        title    : movie.title,
        director : movie.director,
        url      : movie.url,
        edit     : movie.edit
      })
    }
  }
}

</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Answer №1

Make sure to set the isEditing variable to true once the user clicks on the Edit button, and be sure to define the movie data.

editMovie: function (movie){
  ...
  this.movie = Vue.util.extend({}, movie); // Use deep cloning to avoid altering the original object
  this.isEditing = true;
},

Answer №2

Following the advice given in the response (from Ben), I included the movie declaration within the initial data object. The updated code now appears as follows:

data () {
    return {
      isEditing: false,
      newMovie: {
        title: '',
        director: '',
        url: 'http://',
        edit: false
      },
      movie: {
        edit: false
      }
    }
  },

The usage of v-if now functions correctly, illustrated by this example:

<div v-if="!movie.edit">

The variable "is Editing" was deemed unnecessary and thus has been eliminated.

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

What is the solution to fixing the JSON parsing error that says 'JSON.parse: bad control character in string literal'?

When sending data from NodeJS Backend to the client, I utilize the following code: res.end(filex.replace("<userdata>", JSON.stringify({name:user.name, uid:user._id, profile:user.profile}) )) //No errors occur here and the object is successfully stri ...

Troubleshooting: Getting 405 or 415 errors when making POST requests from Vue.js to .NET Web API 2

I'm currently struggling with POSTing data to my WEBAPI. Here is the ASP.NET WEBAPI code that I am using: [RoutePrefix("api/Test")] public class TestController : ApiController { // GET: api/Test [Route] public IEnumerable& ...

Is it possible to restrict contenteditable elements to only accept numbers?

Is there a way to restrict contenteditable elements such that only numerical values can be entered? I attempted to use the following code snippet: onkeypress='return event.charCode >= 48 && event.charCode <= 57' However, despite a ...

Tips for effectively incorporating additional directives into a directive as it is being defined

I'm encountering a significant issue with dynamic directives in angularjs. My goal is to include new directives to a directive while defining it through an object: compile: function () { return { pre: function (scope, iElement, iAttrs) { ...

Accessing dynamically created AJAX controls in ASP.NET during postback operations

I am dynamically creating 2 dropdown boxes and a CheckBoxList control using AJAX callbacks to a web service (.asmx file). The server-side service generates the Dropdowns and CheckBoxList, returning the rendered html as a string which is then inserted into ...

Creating dynamic ng-options in AngularJS

Below is an array: $scope.age = 2; $scope.people = [{name:"Sam",age:2},{name:"Pam",age:3},{name:"Ham",age:4}] The requirement is to make the ng-options dynamic. When age is 2, display all people objects in ng-options. If age is 1, show only the object wi ...

Do you need to define a schema before querying data with Mongoose?

Is it necessary to adhere to a model with a schema before running any query? And how can one query a database collection without the schema, when referred by the collection name? This scenario is demonstrated in an example query from the Mongoose document ...

Discover the hidden truth: Unveiling the enigma of React

I'm currently learning React and I've been working on some apps to enhance my skills and deepen my understanding. Right now, I am facing a challenge where I need to incorporate the logged user information into the Redux state. However, whenever I ...

How to keep text always locked to the front layer in fabric.js without constantly bringing it to the front

Is it possible to achieve this functionality without using the following methods? canvas.sendBackwards(myObject) canvas.sendToBack(myObject) I am looking to upload multiple images while allowing them to be arranged forward and backward relative to each o ...

react-full-page is causing my webpage to not open in a specific ID location, such as http://localhost:3000/#someIdWhereIWantThePageToBeOpened

I'm currently utilizing the react-full-page package and while it's almost working well, I've come across two issues: After clicking on an anchor link like <a href='#someId'>Go There</a>, the scroll goes to the designat ...

JavaScript bug with URL encoding in Internet Explorer 11

I am encountering an issue with Internet Explorer 11 (IE 11) when attempting to call a JavaScript URL function. The problem lies with the URL parameter value, which is in Unicode format but the result displays as ????? instead of Unicode characters. Belo ...

Can directive interception be utilized in Vue to modify the template rendering process?

Can Vue be directed not to render a template? For example <div v-prevent-render>{{ variable }}</div> will display {{ variable }}, but not the value of variable ---update--- Actually, I intended to perform some operations before rendering, ...

Tips on building a carousel with slot elements

Many people have shown me the traditional way of creating a carousel using an array of images. However, I find this method to be limiting because I want each slide of my carousel to include a lightbox component. Instead of having to rewrite the lightbox fu ...

How can input be prevented on keydown within angular6?

Is there a way to disable the input field only when a keydown event occurs, without affecting other input fields? xyz.component.html <input type="text" (keydown)="disableInput($event)"> // <-- Disable if keydown <input type="text" (keydown) ...

The delete button in the "Chip" component of React Material-UI is not functioning as expected

I'm having trouble with the "Chip" control and its "X" button functionality. Unlike the examples shown here: http://www.material-ui.com/#/components/chip Adding the "onRequestDelete" property does include the "X" button, but it doesn't respond t ...

Troubleshooting issue with JQuery AJAX loading Bootstrap Dropdowns

I have a website on GitHub Pages that uses Bootstrap, but I'm having issues with the drop-down menu in the navbar. Sometimes it works and sometimes it doesn't. I am using $("#nav").load("url"); to load the navbar so that I can make changes and ha ...

Securing my private key on a webpage from potential exposure by mandrillapp

After successfully creating and adding the key in Mandrill, I am able to send emails from my JavaScript page hosted at this link: However, I am facing an issue where my Mandrill key is publicly visible (in the contact_me.js file). I attempted to restrict ...

Using JavaScript with namespaces in C#

I am currently trying to explore AJAX and web services through self-teaching using C# and JavaScript. After doing some research on Google, it seems like I might be facing a namespace problem. Here is the snippet of my code: using System; using System.Col ...

Ways to clear TextField status

My question is about a Textfield. In the case where the state is null but the text field value is showing in the Textfield. <TextField style={{ width: '65%'}} id="standard-search" ...

Personalized search feature for Bootstrap tables

Below is the table structure: <table> <tr> <th>Number</th> <th>Name</th> </tr> <tr> <td>200.10.1234</td> <td>Maria Anders</td> </tr> <tr> < ...