[Vuejs]-How to update a vue js array with user inputed value

0👍

It sounds like what you want is a component which you toggle to be either in a read-only mode, or in a mode which accepts input for your admin users. You can then use this in your v-for loop to bind to the array of data.

You can still use v-model with custom components to facilitate two-way binding as described here. Basically, v-model will supply the value to the component via the value property, and will listen for an input event from the component to receive updates to the value.

So, our component template could look like the below, which conditionally renders an input field if the prop edit is true, otherwise it renders a read-only span element. We bind the value of the input to a local mutable data item we initialise from the value prop v-model will pass in from the parent. On the input event as the user changes the value, it will in turn emit an event of the same name so the parent component can receive updates.

<input 
     v-if="edit" 
     type="text" 
     v-model="localValue" 
     @input="$emit('input', $event.target.value)" 
     class="form-control" />
<span v-else>{{ value }}</span>

With a backing script like this:

var customInputComponent = {
  template: '#input-template',
  props: ["edit", "value"],
  data() { 
    return {
      localValue: this.value
    }
  }
};

In the parent element, the usage of the component in the template would look like this, where we register the custom input component with the name appCustomInput. We use v-model to bind the component to the current item of the iteration and the property for that particular column. Finally, we bind the edit prop of the custom component to a data field editMode on the parent with :edit="editMode" (short cut for v-bind:edit="editMode").

It is important to set the :key="searchResult.id" to uniquely identify each entry, otherwise there will be problems when updating the DOM when the value changes. We can’t use just the index for this, because if we remove an item from the courses array, it will no longer be correct. So, I’ve added a unique id property to each of the course objects.

<tr v-for="(searchResult, index) in searchCourses" :key="searchResult.id">
    <th scope="row"> 
      {{ index + 1 }}            
    </th>
    <td>
      <app-custom-input v-model="searchResult.topic" :edit="editMode" />
    </td>
    <td>
      <app-custom-input v-model="searchResult.description" :edit="editMode" />
    </td>
    <td v-if="editMode">
      <button 
              v-if="editMode" 
              class="btn btn-secondary"
              @click="deleteRow(searchResult.id)">Delete</button>
    </td>
</tr>

The backing instance code for this would look something like this:

new Vue({
    el: "#app",
    components: {
      appCustomInput: customInputComponent
    },    
    data: {
      search: '',
      editMode: false,
      courses: [  
        { topic: "English", description: "Universal language", id: 1 },
        { topic: "Maths", description: "Numbers etc.", id: 2 },
        { topic: "Physics", description: "Falling apples etc.", id: 3 },
        { topic: "Chemistry", description: "Periodic table etc.", id: 4 }
      ]    
    },
    methods: {
      deleteRow(sourceId) {
        var index = this.courses.findIndex(a => a.id == sourceId);
        this.courses.splice(index, 1);
      }
    },
    computed: {
      searchCourses() { 
        return this.courses
        .filter((item) => {
          return item.topic
            .toLowerCase()
            .includes(this.search.toLowerCase())
        });
      }
    }
  });

A complete code pen is available here for demonstration.

0👍

The {{ }} "mustache" syntax is used to display values, so the expression between the double braces will be evaluated and the output will replace it. This is a one-way process. You’re most likely looking for a two-way binding which does not only change your UI if the property changs, but also change the property when a user changes it from the UI, hence the name.

Have a look at Input bindings. Where v-model is the key:

<input v-model="item.topic">

Leave a comment