2

I have a simple admin app that creates new businesses via form and adds them to a table. I have created methods to add and delete entries, but am not sure how to proceed creating an update method. The content is contenteditable and I want to save that on save button click. Please see my CodePen: http://codepen.io/Auzy/pen/177244afc7cb487905b927dd3a32ae61 To do this I use VueJS and Vuefire the following way (pardon the Bootstrap):

  <!-- Table -->
  <table class="table table-striped">
  <tr>
    <th>Business Name</th>
    <th>Vanity URL</th>
        <th>Story</th>
    <th>Actions</th>
  </tr>
  <tr v-for="post in posts" :key="post['.key']">
    <td contenteditable v-model="newPost.title">{{post.title}}</td>
    <td>{{post.content}}</td>
        <td>{{post.story}}</td>
    <td>
              <button v-on:click="removePost(post)" type="button" class="btn btn-default btn-sm"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit</button>
  <button v-on:click="removePost(post)" type="button" class="btn btn-danger btn-sm"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete</button>
        </td>
  </tr>
  </table>
</div>
</div>

And JS:

// Setup Firebase
let config = {
  ...firebase stuff...
}

let firebaseapp = firebase.initializeApp(config);
let db = firebaseapp.database();
let postsRef = db.ref('blog/posts')

// create Vue app
var app = new Vue({
  // element to mount to
  el: '#app',
  // initial data

  data: {
    newPost: {
      title: '',
      content: '',
            story: ''
    }
  },
  // firebase binding
  // https://github.com/vuejs/vuefire
  firebase: {
    posts: postsRef
  },
  // methods
  methods: {
      addPost: function () {
        postsRef.push(this.newPost);
        this.newPost.title = '';
        this.newPost.content = '';
        this.newPost.story = '';
      },
    removePost: function (post) {
      postsRef.child(post['.key']).remove()
            toastr.success('Business removed successfully')
    }
  }
})

1 Answer 1

3

You have to use $bindAsArray for arrays and $bindAsObject for objects to bind firebase data to component data.

You can use $firebaseRefs which is provided by vuefire to update or modify the endpoints.

Here is the updated codepen.

I have made the following changes to your code.

// create Vue app
var app = new Vue({
  // element to mount to
  el: '#app',
  // initial data

  data: {
    posts: [], // All the business post to display
    newPost: {
      title: '',
      content: '',
      story: ''
    }
  },
  // methods
  methods: {
        addPost: function () {
            postsRef.push(this.newPost);
            this.newPost.title = '';
            this.newPost.content = '';
            this.newPost.story = '';
        },
        editPost: function(post) {
            // Set post values to form
            this.newPost = post
        },
        updatePost: function(post) {
            const childKey = post['.key'];
            /*
             * Firebase doesn't accept speacial chars as value
             * so delete `.key` property from the post
             */
            delete post['.key'];
            /*
             * Set the updated post value
             */
            this.$firebaseRefs.posts.child(childKey).set(post)
        }, 
        removePost: function (post) {
         postsRef.child(post['.key']).remove()
         toastr.success('Business removed successfully')
        }, 

  },
    // Explicitly set binding data to firebase as an array.
    created() {
        this.$bindAsArray('posts', postsRef);
    }
})

In the template:

<div id="app">
 <ul class="nav nav-pills nav-justify">
        <li role="presentation" class="active"><a href="#">Businesses</a></li>
        <li role="presentation"><a href="#">Events</a></li>
        <li role="presentation"><a href="#">Locations</a></li>
 </ul>
 <br />
  <div class="panel panel-default">
    <div class="panel-heading">
     <h3 class="panel-title">Add a Business</h3>
    </div>
    <div class="panel-body">
     <form id="form">
      <div class="form-group">
        <label for="exampleInputPassword1">Business Name</label>
        <input v-model="newPost.title" type="text" class="form-control" id="exampleInputPassword1" placeholder="Business Name">
      </div>

      <div class="form-group">
        <label for="basic-url">Vanity URL</label>
        <div class="input-group">
        <span class="input-group-addon" id="basic-addon3">/businesses/</span>
        <input v-model="newPost.content" type="text" class="form-control" id="basic-url" aria-describedby="basic-addon3">
      </div>
    </div>
    <div class="form-group">
     <label for="basic-url">Description</label>
     <textarea v-model="newPost.story" name="" id="" cols="30" rows="10"></textarea>
     </div>
     <button type="button" class="btn btn-default" v-if="newPost['.key']" v-on:click="updatePost(newPost)">Update</button>
     <button type="submit" class="btn btn-default" v-if="!newPost['.key']" v-on:click="addPost">Add Business</button>
</form>
</div>
    </div>

    <div class="panel panel-default">
        <!-- Default panel contents -->
        <div class="panel-heading">Businesses</div>

        <!-- Table -->
        <table class="table table-striped">
            <tr>
                <th>Business Name</th>
                <th>Vanity URL</th>
                <th>Story</th>
                <th>Actions</th>
            </tr>
            <tr v-for="post in posts" :key="post['.key']">
                <td contenteditable v-model="newPost.title">{{post.title}}</td>
                <td>{{post.content}}</td>
                <td>{{post.story}}</td>
                <td>
                    <button v-on:click="editPost(post)" type="button" class="btn btn-default btn-sm"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit</button>
                    <button v-on:click="removePost(post)" type="button" class="btn btn-danger btn-sm"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete</button>
                </td>
            </tr>
        </table>
    </div>

    <ul class="errors">
    </ul>
</div>
Sign up to request clarification or add additional context in comments.

1 Comment

Srinivas Damam, I've looked at your example in codepen and I realized that it has the same problem that i'm looking for to solve. When you click on edit button you just call the 'editPost' method, but if you call the 'updatePost' instead and do a real change to te post like: post.title = "foo, you will notice that it changes not only the post that you have clicked on but also the other one. Do you have any idea why?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.