Ong Kong Tat
Ong Kong Tat

Reputation: 1242

How to add input for each field after clicking edit in a table using jquery?

I would like to know how to add input to each field in a table once I press edit using jquery. So basically I have 7 columns with 7 headings in the table for html and I want to be able to edit each field after pressing edit button which will be at the right side of the table for each row. After I add the input field in each column for that specific row and once the input is in, I want to call my update api using ajax. This is my html code.

<div id="table-wrapper"> 
    <div id="table-scroll">
    <table id="results" class="hidden" cellspacing=10px>
        <thead>
            <tr class = "spacing">
                <th>SAM ID</th>
                <th>Item Description</th>
                <th>Issued QTY</th>
                <th>Opening QTY</th>
                <th>Closing QTY</th>
                <th>Corrupted QTY</th>
                <th>Remarks</th>
            </tr>
        </thead>
        <tbody id="bResults">
        </tbody>
    </table>
    </div>
    </div>

This is my js code connected to the html.

function search(){

var samId = $('#samId').val();
var postData = { "samId": samId };
var postJSON = JSON.stringify(postData);
$.ajax({
    url: "http://localhost:3000/api/queryRecord", // server url
    type: "POST", //POST or GET
    contentType: "application/json",
    data: postJSON, // data to send in ajax format or querystring format
    dataType : "JSON", //dataType is you telling jQuery what kind of 
    response to expect
    success: function(response) {
        alert('success');
         if(response){
            var len = response.length;
            var txt = "";
            if(len > 0){
                for(var i=0;i<len;i++){
                    if(response[i].samID && response[i].itemDescription){
                        txt += "<tr class='rowdata'><td>"+response[i].samID 
                        +"</td><td>"+response[i].itemDescription+"</td><td>"
                        +response[i].issuedQTY + "</td>
                        <td>"+response[i].openingQTY + "</td>
                        <td>"+response[i].closingQTY
                        +"</td><td>"+response[i].corruptedQTY+"</td>
                        <td>"+response[i].Remarks+"</td><td>" 
                        + "<input class='button-edit' type='submit' 
                        value='Edit' onclick = 'edit()' />" 
                        +"</td></tr>";
                    }
                }

                $("#bResults").empty();
                if(txt != ""){
                    $("#results").removeClass("hidden");
                    $("#bResults").append(txt);
                }
            }
        }
    },
    error: function(response) {
        alert('error');
    }
});
event.preventDefault();
}

 function edit(){
 var currentTD = $(this).parents('tr').find('td');
      if ($(this).html() == 'Edit') {                  
          $.each(currentTD, function () {
              $(this).prop('contenteditable', true)
          });
      } else {
         $.each(currentTD, function () {
              $(this).prop('contenteditable', false)
          });
      }

      $(this).html($(this).html() == 'Edit' ? 'Save' : 'Edit')
}

My search() works fine but just wanted to show how my response is being coded. This edit() is what I have basically but I don't really know how to use as the code is from another question Making row editable when hit row edit button due to not having any clue about the way to do this edit and adding a input field for people to edit in that particular row. I am using mongodb as the database as well. Do explain it in a simpler way for me to understand better. Thanks!

UPDATE Following according to Mohamed-Yousef

function search(){

var samId = $('#samId').val();
var postData = { "samId": samId };
var postJSON = JSON.stringify(postData);
$.ajax({
    url: "http://localhost:3000/api/queryRecord", // server url
    type: "POST", //POST or GET
    contentType: "application/json",
    data: postJSON, // data to send in ajax format or querystring format
    dataType : "JSON", //dataType is you telling jQuery what kind of 
    response to expect
    success: function(response) {
        alert('success');
         if(response){
            var len = response.length;
            var txt = "";
            if(len > 0){
                for(var i=0;i<len;i++){
                    if(response[i].samID && response[i].itemDescription){
                        txt +="<tr class='rowdata'><td>"+response[i].samID+ 
                              "</td>"+<td>"+response[i].itemDescription+
                               "</td>"+"<td>"+response[i].issuedQTY + 
                               "</td>"+"<td>"+response[i].openingQTY + 
                               "</td>"+"<td>"+response[i].closingQTY+
                               "</td>"+"<td>"+response[i].corruptedQTY+
                               "</td>"+"<td>"+response[i].Remarks+"</td>"
                               +"<td><input class='button-edit' 
                               type='submit' value='Edit' onclick = 'edit()' 
                               /></td>"+"</tr>";
                    }
                }

                $("#bResults").empty();
                if(txt !== ""){
                    $("#results").removeClass("hidden");
                    $("#bResults").append(txt);
                }
            }
        }
    },
    error: function(response) {
        alert('error');
    }
});
event.preventDefault();
}
 function edit(el){
 var currentTD = $(el).closest('tr').find('td').not($(el).closest('td'));
      if ($(this).html() == 'Edit') {                  
          $.each(currentTD, function () {
              $(this).prop('contenteditable', true)
          });
      } else {
         $.each(currentTD, function () {
              $(this).prop('contenteditable', false)
          });
      }

      $(el).val($(el).val() == 'Edit' ? 'Save' : 'Edit')
}

Does not seem to work and still gives the error Uncaught TypeError: Cannot read property 'createDocumentFragment' of undefined

Another answer I did according to Bryan Dellinger was using knockout.js

<table id="results" class="hidden" cellspacing=10px>
        <thead>
            <tr class = "spacing">
                <th>SAM ID</th>
                <th>Item Description</th>
                <th>Issued QTY</th>
                <th>Opening QTY</th>
                <th>Closing QTY</th>
                <th>Corrupted QTY</th>
                <th>Remarks</th>
            </tr>
        </thead>

             <tbody id="bResults" data-bind="foreach: txt">
        <tr>
            <td>
   <!-- ko if: buttonText() === 'Save' -->
            <input data-bind="textInput: samID">
   <!-- /ko -->
       <!-- ko if: buttonText() === 'Edit' -->
            <span data-bind="text: samID"></span>
   <!-- /ko -->
            </td>
        <td>
   <!-- ko if: buttonText() === 'Save' -->
            <input data-bind="textInput: itemDescription">
   <!-- /ko -->
       <!-- ko if: buttonText() === 'Edit' -->
            <span data-bind="text: itemDescription"></span>
   <!-- /ko -->
        </td>
        <td>
    <!-- ko if: buttonText() === 'Save' -->
            <input data-bind="textInput: issuedQTY">
   <!-- /ko -->
       <!-- ko if: buttonText() === 'Edit' -->
            <span data-bind="text: issuedQTY"></span>
   <!-- /ko -->
        </td>
        <td>
    <!-- ko if: buttonText() === 'Save' -->
            <input data-bind="textInput: openingQTY">
   <!-- /ko -->
       <!-- ko if: buttonText() === 'Edit' -->
            <span data-bind="text: openingQTY"></span>
   <!-- /ko -->
        </td>
        <td>
    <!-- ko if: buttonText() === 'Save' -->
            <input data-bind="textInput: closingQTY">
   <!-- /ko -->
       <!-- ko if: buttonText() === 'Edit' -->
            <span data-bind="text: closingQTY"></span>
   <!-- /ko -->
        </td>
        <td>
    <!-- ko if: buttonText() === 'Save' -->
            <input data-bind="textInput: corruptedQTY">
   <!-- /ko -->
       <!-- ko if: buttonText() === 'Edit' -->
            <span data-bind="text: corruptedQTY"></span>
   <!-- /ko -->
        </td>
        <td>
    <!-- ko if: buttonText() === 'Save' -->
            <input data-bind="textInput: corruptedQTY">
   <!-- /ko -->
       <!-- ko if: buttonText() === 'Edit' -->
            <span data-bind="text: corruptedQTY"></span>
   <!-- /ko -->
        </td>
                    <td>
    <!-- ko if: buttonText() === 'Save' -->
            <input data-bind="textInput: Remarks">
   <!-- /ko -->
       <!-- ko if: buttonText() === 'Edit' -->
            <span data-bind="text: Remarks"></span>
   <!-- /ko -->
        </td>
        <td><button data-bind="text: buttonText, click: $parent.click">
        </button></td>
        </tr>
        </tbody>
    </table>
  <script src="js/jquery-3.2.1.min.js"></script>
  <script src="js/mainpage.js"></script>
  <script 
  src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-
   min.js"></script> 
  <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1
  /knockout.mapping.min.js"></script>  

This is the js

function search(){

var samId = $('#samId').val();
var postData = { "samId": samId };
var postJSON = JSON.stringify(postData);
$.ajax({
    url: "http://localhost:3000/api/queryRecord", // server url
    type: "POST", //POST or GET
    contentType: "application/json",
    data: postJSON, // data to send in ajax format or querystring format
    dataType : "JSON", //dataType is you telling jQuery what kind of response to expect
    success: function(response) {
        alert('success');
         if(response){
            var len = response.length;
            var txt = "";
            if(len > 0){
                for(var i=0;i<len;i++){
                    if(response[i].samID && response[i].itemDescription){
                        txt = [{
                                "samID": response[i].samID,
                              "itemDescription":response[i].itemDescription,
                               "issuedQTY": response[i].issuedQTY,
                                "openingQTY": response[i].openingQTY,
                                "closingQTY": response[i].closingQTY,
                                "corruptedQTY": response[i].corruptedQTY,
                                "editMode" : false,
                                "Remarks": response[i].Remarks,
                                "buttonText": "Edit"
                        }]
                    }
                }

                $("#bResults").empty();
                if(txt != ""){
                    $("#results").removeClass("hidden");
                    $("#bResults").append(txt);
                }
            }
        }
    },
    error: function(response) {
        alert('error');
    }
});
event.preventDefault();
}

Upvotes: 0

Views: 2215

Answers (1)

Mohamed-Yousef
Mohamed-Yousef

Reputation: 24001

I think The problem is : by using $(this) inside your edit() function its refer to object I don't know for window or something but its not for an edit button .. so you can pass edit(element) as an argument and on html use onclick="edit(this)"

And while you use input .. use .val() instead of .html()

And to avoid the td which has your edit input you can use .not()

so your code should looks like

function edit(el){
 var currentTD = $(el).closest('tr').find('td').not($(el).closest('td')); // tds except the td which closest to the edit button
 if ($(el).val() == 'Edit') {                  
     $.each(currentTD, function () {
       $(this).prop('contenteditable', true)
     });
  } else {
     $.each(currentTD, function () {
       $(this).prop('contenteditable', false)
     });
  }

  $(el).val($(el).val() == 'Edit' ? 'Save' : 'Edit')
}

And on html use type="button" no need to use submit

<input class='button-edit' type='button'  value='Edit' onclick = 'edit(this)' /> 
//--------------------------------^-------------------------------------^--------

And the row HTML structure should be like

txt += "<tr class='rowdata'><td>"+response[i].samID+"</td>"
  +"<td>"+response[i].itemDescription+"</td>"
  +"<td>"+response[i].issuedQTY + "</td>"
  +"<td>"+response[i].openingQTY + "</td>"
  +"<td>"+response[i].closingQTY+"</td>"
  +"<td>"+response[i].corruptedQTY+"</td>"
  +"<td>"+response[i].Remarks+"</td>"
  +"<td><input class='button-edit' type='submit' value='Edit' onclick = 'edit()' /></td>" 
  +"</tr>";

And use !== instead of != in if(txt != ""){

Upvotes: 1

Related Questions