Vue.js same form for add and edit

16,810

Solution 1

You should change the isEditing to true when the Edit button clicked, and you should define the data movie.

editMovie: function (movie){
  ...
  this.movie = Vue.util.extend({}, movie); // deep clone to prevent modify the original object
  this.isEditing = true;
},

Solution 2

As suggested in the comments (by Ben), I added the movie declaration to the initial data object. So now it looks like this:

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

Now v-if works just fine, like this:

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

"is Editing" was no longer necessary so I removed it.

Share:
16,810
kilinkis
Author by

kilinkis

Advocate web developer

Updated on June 04, 2022

Comments

  • kilinkis
    kilinkis about 2 years

    I'm a rookie on vue.js and I'm trying to extend some tutorials a completed. Been fighting with this three hours now and I'm frustrated. FYI, I'm using firebase but I'm not sure it really matters here.

    So, I have a CRUD app for listing movies (I told you it was basic!). There is a form at the top of the page where you can add movies, and a table below it, where the new registries are listed. This works well.

    I added Edit and Delete buttons to each row on the table. The delete function works. But the Edit function is the problem.

    I'd like to use v-if on the initial form, to trigger different methods (save, edit) and show different buttons (Add, Save, Cancel).

    I'm not sure how to access the objects to do this, I tried a couple of things and the v-if says the object is not defined.

    thank you for reading, please ask anything you need.

    import './firebase' // this has my credententials and initializeApp
    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, // maybe this helps?
          newMovie: {
            title: '',
            director: '',
            url: 'http://',
            edit: false // or maybe 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 }); // can't access this one with v-if, not sure 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>