VueJs: how to edit an array element

Simple Todo-App. Please excuse my ignorance for asking a rather simple question.

But how would you go and edit a specific item in an array?

I usually try to bind the value of my input to a new property in my data object and then assign that new property to the old property when two-way data binding on a click through Vue.

Like this: http://jsfiddle.net/z7960up7/

In my case, I am using a v-repeat directive that goes through my dataset, but I cannot use the v-model directive to use two-way data binding, as the property values ​​would get corrupted if I do it like this. (See here: http://jsfiddle.net/doL46etq/2/ )

And now I'm wondering how I will update my task array:

My idea is to pass the VueObject (this) through my method on click and then define the index in my event handler and then update the task array using the index, like so:

HTML:

<input v-el="editInputField" type="text" value="{{ task.body }}" v-on="keyup: doneEdit(this) | key 'enter'"/>

<button v-on="click: editTask(this)">
     Edit
</button>

      

JS:

methods: {
    editTask: function (task) {
        var taskIndex = this.tasks.indexOf(task.task);

        this.tasks[taskIndex] = {
            'body': document.querySelector('input').value,
            'completed': false
        };

        console.log(task.task.body);
    },
}

      

Here is my violin:

http://jsfiddle.net/doL46etq/3/

But the data object doesn't update at all and I'm wondering how I would go about doing that and update it.

What's the best way to edit an element in an array using Vue?

Edit: Easy way: just remove the item and add a new one to the array using the push method, but I really want to just update the item because I like to keep the data file in sync with my server.

+3


source to share


2 answers


In fact, the easiest way to update an array element is to double-bind the task body using the v-model directive .

Example:

http://jsfiddle.net/z7960up7/2/



<div id="demo">
    {{ message }}

    <div class="edit">
        <input type="text" v-model="message">         
        <button v-on="click: editMessage">Edit</button>
    </div>        
    <pre>{{ $data | json }}</pre>
</div>

      

And fire an event when you blur the input box or the edit button is pressed.

Also hide the input field with css using the v-class directive .

+2


source


Short answer: use the component in the extended constructor, then pass the index to that component as an HTML property, and use the calculated properties to reference back and forth to your data.

But don't be satisfied with just a short answer. Here's the long one:

Situation: I am using a JSFiddle as the basis for this answer.

in the HTML you have:

<td>{{ task.body }}</td>
                <td>
                    <div>
                        <input v-el="editInputField" type="text" value="{{ task.body }}" v-on="keyup: doneEdit(this) | key 'enter'" v-model="newEdit"/>
                    </div>
                </td>
                <td>
                    <button v-on="click: editTask(this)" class="mdl-button mdl-js-button mdl-button--icon"> <i class="material-icons">create</i>

                    </button>
                </td>

      

We want to replace this code with a component. Using this component allows us to identify the index / row we are working on in your dataset.

<td v-component="listitem" index="{{$index}}"></td>

      

Next step: defining the component.

In order not to cloud our instance with a component, we will create a separate constructor for the vue object, so we can assign a new element to our new object.

This is done using an extension.



window.newVue =  Vue.extend({
components:
{
    'listitem': {

        props: ['index'],

        computed: {
        // both get and set
        body: {
          get: function () {

            return this.$parent.tasks[this.index].body;
          },
          set: function (v) {
            this.$parent.tasks[this.index].body = v
          }
        }
      },
        template: '<td>{{ body }}</td><td><div><input type="text" v-model="body" value="{{ body }}"/></div></td><td></td>',
    }
}

      

});

Since we cannot correctly define our data using the extension, we will simply assume that the data already exists when we write the component.

Step 3: defining the actual data: Instead of using Vue as our object constructor, we will now use our newly created instance.

new newVue({
el: '#todoapp',

data: {
    tasks: [{
        'body': 'Eat breakfast',
        'completed': false
    }, {
        'body': 'Drink milk',
        'completed': false
    }, {
        'body': 'Go to the store',
        'completed': false
    }],

    newTask: '',
},

      

});

What is it!

If you could not follow up on what happened: here's the Fiddle!

PS: More details on how this code works can be found at vuejs.org

+3


source







All Articles