What is the best way to select specific elements within a table cell with vuejs?

I am facing an issue with a dynamically rendered table where each cell contains data in a readonly input box. The first cell has an edit button, and when clicked, the input boxes should become editable for user input. The edit button should then be hidden, and a save button should appear. Upon clicking save, a method needs to be triggered to handle the saved data, such as storing it in a database.

I attempted to access the event and target but encountered an array that I'm not sure how to handle. Any suggestions on how to approach this?

<div id="app">
<table border=1 width=100%>
  <tr>
    <td width=10px>EDIT</td>
    <td>Program</td>
    <td>Company</td>
    <td>Funding</td>
    <td>Funded</td>
    <td>Recruit</td>
  </tr>
  <tr v-for="program in programs">
    <td><button class="show" v-on:click="editItem($event)">edit</button>&nbsp;<button class="hide">save</button></td>    
    <td><input type="text" v-bind:data-id="program.id" readonly="readonly" v-model="program.program"></td>
    <td><input type="text" v-bind:data-id="program.id" readonly="readonly" v-model="program.company"></td>
    <td><input type="text" v-bind:data-id="program.id" readonly="readonly" v-model="program.funding"></td>
    <td><input type="text" v-bind:data-id="program.id" readonly="readonly" v-model="program.funded"></td>
    <td><input type="text" v-bind:data-id="program.id" readonly="readonly" v-model="program.Recruit"></td>
  </tr>
</table>
</div>

new Vue({
  el:"#app",
  data() {
    return {
      test:"hello",
      programs:"",
      hide:true
    }
  },
  created: function(){
    this.getPrograms();
  },
  mounted: function(){

  },
  methods: {
    getPrograms: function(){
     axios.get("https://my-json-server.typicode.com/isogunro/jsondb/Programs").then((response) => {
        this.programs = response.data;
      })
      .catch(function (error) {
        console.log(error);
      });
    },
    editItem: function(e){     
      console.log(e)
       //console.log(e.target.parentElement.parentNode.parentElement.HTMLCollection) doesn't work
      alert("Make line item editable for editing and then saving")
    }
  }
})

For further reference, here's the link to the pen.

Answer №1

i copied your pen here or try it like this:

Vue.config.devtools = false
Vue.config.productionTip = false

new Vue({
  el:"#app",  
  filters: {
    toCapitalize (text) {
      return text.charAt(0).toUpperCase() + text.slice(1)
    }
  },  
  data () {
    return {
      columns: [
        'program', 'company', 'funding', 'funded', 'Recruit'
      ],
      programs: []
    }
  },
  created () {
    this.getPrograms()
  },
  methods: {
    getPrograms () {
      axios.get("https://my-json-server.typicode.com/isogunro/jsondb/Programs")
        .then(response =>
          // adding prop isEditable for each object    
          this.programs = response.data.map(program => ({ isEditable: false, ...program }))
        )
        .catch(error => console.log(error))
    },
    // using index of the current program to toggle the property isEditable
    editItem (index) {
      this.programs[index].isEditable = !this.programs[index].isEditable
    }
  }
})
.editable {
  border: 2px solid green
}
.button-action {
  min-width: 3rem
}
input {
  width: 100%;
}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>

<div id="app">
  <table border=1 width=100%>
    <tr>
      <td width=10px>EDIT</td>
      <td v-for="(column, indexColumn) in columns" :key="indexColumn">
        {{ column | toCapitalize }}
      </td>
    </tr>
    <tr v-for="(program, indexProgram) in programs" :key="indexProgram">
      <td>
        <button 
          @click="editItem(indexProgram)"
          class="button-action"
        >
          {{ program.isEditable ? 'save' : 'edit' }}
        </button>
      </td>    
      <td v-for="(column, indexColumn) in columns" :key="indexColumn">
        <input        
          v-model="program[column]"
          :readonly="!program.isEditable"
          :class="{ 'editable': program.isEditable }"
        >
      </td>
    </tr>
  </table>
</div>

Answer №2

When obtaining a list of programs, include an additional property to indicate if the row is in edit mode:

axios.get(url).then (response => {
    this.programs = response.data.map(item => {
        ...item,
        isEditing: false
    })
}) 

Furthermore, make sure that programs are initialized as an empty array rather than an empty string.

In the editItem method, pass a reference to the item instead of the event object and set isEditing to true:

editItem(item) {
    item.isEditing = true
}

Create a method to determine if the row input is in readonly mode:

isReadOnly(item) {
    return item.isEditing ? false : "readonly";
}

Bind this method to the readonly attribute of the input:

<input type="text" :readonly="isReadOnly(item)" />

Avoid using node references and instead utilize binding to solve the issue. For instance, bind the button title to a method that returns either "Save" or "Edit" based on the isEditing state.

Answer №3

To keep track of the program row being edited, create a property for it.
Instead of creating a new property, utilize the existing program.id property for this purpose.

The editingId vm property is used to identify which "program" is currently being edited. If this property is not null, the readonly attribute will be set to false, and the button will switch from edit to save. Resetting the editingId property to null will return the table to its normal view mode.

I have added a saveItem v-on:click callback to the save button to demonstrate setting the editingId property back to null. Feel free to customize this callback as needed, just ensure that you reset the editingId property to null to exit edit mode.

Check out the changes in this updated pen

Answer №4

Change the read-only status of elements within an array. When you click the edit button, switch the read-only attribute from true to false for all elements in the array.

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

Leveraging Angular for REST API Calls with Ajax

app.controller('AjaxController', function ($scope,$http){ $http.get('mc/rest/candidate/pddninc/list',{ params: { callback:'JSON_CALLBACK' } }). success(function (data, status, headers, config){ if(ang ...

Jquery Position behaving unexpectedly during initial invocation

My goal is to have the autocomplete menu open above the input box if there is not enough space below it. The code functions properly, except for the initial render. It consistently displays at the bottom in the following scenarios: 1. When starting a searc ...

Using Angular to retrieve data from a JSON file correlating with information in another JSON file

Just starting out with angular and facing a problem where I'm unsure of the best approach to setting up this code efficiently. I have 2 JSON files: images.json { "imageName": "example.jpg", "imageTags": ["fun","work","utility" ...

Using Javascript to parse a regular expression in a string

I am facing a challenge with a JavaScript string that contains contact information that needs to be filtered. For example, I want to mask any email or phone number in the message. I have attempted the following approach: function(filterMessage) { ...

Preventing event propagation in jQuery's click handler

Is it possible to prevent the propagation of a click event on a dynamically created div within its parent div? HTML <div id = "parent"> Some Stuff </div> Jquery $('#parent').click(function(){ $(this).append('<div class = ...

Tips for conducting an HTTP request test within my application

I am currently facing a challenge while attempting to develop unit tests for my application. Within my controller, I have the following code snippet: $scope.test1 = function() { productFactory.getName() .then(function(products){ ...

Test results indicate successful completion of tests for VueJS component files, however code coverage does not reflect this for those

Currently, I am facing an issue while trying to obtain code coverage results for my VueJS frontend application. It seems that when I create a component and write a snapshot test for it, the file is being ignored by WebStorm. After some investigation, I di ...

Tips for delivering a PDF document to a recipient

I am looking to utilize the GET method in React.js to send an address and download a PDF file. The fileID variable holds the address of the file on the server side. Even after adding { mode: 'no-cors'}, I encountered an error. viewHandler = a ...

What could be the reason for receiving an array of promises instead of data while fetching information from the blockchain using useEffect?

I've encountered an issue while working with React and fetching data from the blockchain using useEffect. The problem arises when I map the data and store it in the lendingData array - upon logging, it appears as though I'm getting an array of pr ...

A JavaScript technique for combining multiple arrays of objects based on a shared key

I am encountering issues with merging two or more arrays as per my desired outcome. I have two arrays named arrCustomer and arrCustomerDetails. They both contain CustomerID as a key, however, I aim to merge all values from arrCustomerDetails while incorpo ...

Why does Vue continuously insert undefined values when adding non-consecutive indexes to an array?

In my application, users can select values from a dropdown list and add them to an array by clicking the "add" button. The goal is to use the selected value's id as the index in the array. For example: List of Values 1 - Apple 3 - Bananas 8 - P ...

Node unable to interpret accented characters from CSV file input

Currently, I am utilizing npm fast-csv as my CSV reader/writer tool. It offers a simple and straightforward way to handle CSV files. My goal is to use this tool along with iconv to deal with "accented" characters and non-ASCII characters by converting them ...

Combining Lists in ImmutableJS Based on Values

I am working with two Immutable.JS lists: const numbers = fromJS([2]); const moreNumbers = fromJS([1, 2]); Is there a way to combine these lists based on their values while keeping the order intact so that the resulting list looks like this? [2, 1] I a ...

How can you access the query in Next.js API when req.query is initially set to undefined?

Is there a way to compare the value of req.query with the cookies on the site, even when req.query is undefined upon initial load? How can this be addressed? export default async function handler(req, res) { const { method } = req; const userId = req ...

Adjust the placement of the div dynamically in response to the positioning of another div tag

I have an icon that resembles a chat bubble. If the position of the icon is not fixed, how can I display the chat bubble relative to the icon and adjust its position dynamically based on the icon's location? See image here #logowrap{ padding: 8px ...

Navigating through JSON data to retrieve specific values and executing repetitive actions

When the form is submitted, I am making an AJAX request to PHP code and this is the response I receive. var data = { "empty":{ "game_sais_no":"Season cannot contain empty value", "game_sc_no":"Category cannot contain empty value", ...

converting an angular object into a string representation

I stumbled upon this guide: . and it includes the following piece of code: import { Component } from '@angular/core'; import { FormGroup, FormControl } from '@angular/forms'; @Component({ selector: 'app-root', templateUrl ...

Tips for modifying a nested reactive form while ensuring validation is maintained?

When retrieving data from a service in the form of an array, one might wonder how to bind this data in a nested form if there are potentially endless entries in the array. The form is expected to be pre-filled with this data, including validation for each ...

Utilizing Jquery.validate() for personalized checkbox validation

My struggle lies in integrating jQuery.validate() with custom-designed checkboxes. I am unable to achieve the desired outcome where, upon clicking SUBMIT without selecting any checkboxes, an error should be displayed in the respective label. Despite having ...

Utilizing key press functionality in JavaScript and jQuery

I have successfully implemented an alert box to display on a key press event. However, I am facing an issue where the alert box pops up even when typing in a textbox on the page. $(document).ready(function() { $(document).keydown(function(e) { ...