skip to Main Content

I have a html table with following structure

<table class="mytable">
   <tbody class="body">
      <tr class="headline1"> ... several td tags with some text ... </tr>
      <tr class="headline2"> ... several td tags with some text ... </tr>
      <tr class="content"> ... several td tags with some text ... </tr>
      <tr class="content"> ... several td tags with some text ... </tr>
      <tr class="content"> ... several td tags with some text ... </tr>
      <tr class="content"> ... several td tags with some text ... </tr>
      <tr class="sum"> ... several td tags with some text ... </tr>
   </tbody>
</table>

The structure of the table cannot be changed. Now I want to replace the lines (<tr> elements) with class "content" and "sum" with the result of an ajax call (search.php generates the same table structure like described before)

My current code looks like:

    $(document).ready(function(){

        const search_field = $('#search_field');

        search_field.keyup(function(){
            $.ajax({
                url:'http://someurl/search.php?search=' + search_field.val(),
                type:"POST",
                success:function(data){
                    var xxx = $(data).find('.body').html();
                    $('.body').html(xxx);
                }
            });
        });
    });

The code works but replaces the whole tbody. I would like to replace only the <tr> elements (with all <td> elements included in the <tr> element). So the two headlines should be kept and not taken from the result of the ajax call.

An easy solution would be to close the <tbody>element after the headlines and create a new <tbody>element with a different id/class. But as already mentioned this is not possible because I cannot change the structure of the table

2

Answers


  1. ...
    success: function(data) {
    $('.content:eq(0)').html( $(data).find('.content:eq(0)').html() );
    $('.content:eq(1)').html( $(data).find('.content:eq(1)').html() );
    $('.content:eq(2)').html( $(data).find('.content:eq(2)').html() );
    $('.content:eq(3)').html( $(data).find('.content:eq(3)').html() );
    $('.sum').html($(data).find('.sum').html());
    }
    

    Or using a loop for .content rows:

    success: function(data) {
    let rows = $('.body .content');
    for(let i = 0; i < rows.length; i++) {
        let selector = '.body .content:eq(' + i + ')'
        $(selector).html( $(data).find(selector).html() );
    }
    }
    
    Login or Signup to reply.
    • Cache your .sum row
    • Remove old .content rows
    • Grab only the .content from the new data HTML
    • Use the .before() method to insert the new rows before your .sum element row
    • Use the .on() method on your Search input. A use could as well paste a value into it, in which case the key events will not register
    const updateTableContent = (data) => {
      const $content = $(".mytable .body .content");
      const $sum = $(".mytable .body .sum");
    
      // 1. remove old .content rows
      $content.remove();
      
      // 2. append new .content rows right before .sum row
      $sum.before($(data).find(".content"));
    };
    
    // Example:
    
    // Just a demo response data mockup:
    const data = `<!DOCTYPE html><html>
    <head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>Test</title>
    </head><body><table class="mytable"><tbody class="body">
      <tr class="headline1"><td>Headline new 1</td></tr>
      <tr class="headline2"><td>Headline new 2</td></tr>
      <tr class="content"><td>Content new 1</td></tr>
      <tr class="content"><td>Content new 2</td></tr>
      <tr class="content"><td>Content new 3</td></tr>
      <tr class="content"><td>Content new 4</td></tr>
      <tr class="content"><td>Content new 5</td></tr>
      <tr class="sum"><td>Sum new</td></tr>
    </tbody></table></body></html>`;
    
    $('#search_field').on("input", function() {
      // AJAX...
          updateTableContent(data);
      //...
    });
    <label>Search: <input id="search_field" type="search"></label>
    <table class="mytable">
       <tbody class="body">
          <tr class="headline1"><td>Headline old 1</td></tr>
          <tr class="headline2"><td>Headline old 2</td></tr>
          <tr class="content"><td>Content old 1</td></tr>
          <tr class="content"><td>Content old 2</td></tr>
          <tr class="content"><td>Content old 3</td></tr>
          <tr class="sum"><td>Sum old</td></tr>
       </tbody>
    </table>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>

    Tip: nowadays, you don’t necessarily need jQuery:

    // DOM utility functions:
    
    const el = (sel, par) => (par || document).querySelector(sel);
    const els = (sel, par) => (par || document).querySelectorAll(sel);
    
    
    // Task: Search fetch data:
    
    const updateTableContent = (data) => {
      const elsContent = els(".mytable .body .content");
      const elSum = el(".mytable .body .sum");
    
      // 1. remove old .content rows
      elsContent.forEach(elCont => elCont.remove());
      
      // 2. append new .content rows right before .sum row
      const doc = new DOMParser().parseFromString(data, "text/html");
      const elsContentNew = els(".content", doc);
      elSum.before(...elsContentNew);
    };
    
    // Example:
    
    // Just a demo response data mockup:
    const data = `<!DOCTYPE html><html>
    <head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>Test</title>
    </head><body><table class="mytable"><tbody class="body">
      <tr class="headline1"><td>Headline new 1</td></tr>
      <tr class="headline2"><td>Headline new 2</td></tr>
      <tr class="content"><td>Content new 1</td></tr>
      <tr class="content"><td>Content new 2</td></tr>
      <tr class="content"><td>Content new 3</td></tr>
      <tr class="content"><td>Content new 4</td></tr>
      <tr class="content"><td>Content new 5</td></tr>
      <tr class="sum"><td>Sum new</td></tr>
    </tbody></table></body></html>`;
    
    const elSearch = el('#search_field');
    elSearch.addEventListener("input", () => {
      const value = elSearch.value.trim();
      //fetch(`https://someurl/search.php?search=${value}`)
      //      .then(res => res.text())
      //      .then(updateTableContent);
      
      // DEMO WITH MOCKUP:
      updateTableContent(data);
    });
    <label>Search: <input id="search_field" type="search"></label>
    <table class="mytable">
       <tbody class="body">
          <tr class="headline1"><td>Headline old 1</td></tr>
          <tr class="headline2"><td>Headline old 2</td></tr>
          <tr class="content"><td>Content old 1</td></tr>
          <tr class="content"><td>Content old 2</td></tr>
          <tr class="content"><td>Content old 3</td></tr>
          <tr class="sum"><td>Sum old</td></tr>
       </tbody>
    </table>

    Anyways, if possible, your search.php should be better rewritten to serve JSON data. Such data can be reused within many other components that do not necessarily use <table>. Also, you don’t necessarily need to use such JSON data from the frontend, but also from other backend scripts. Think about it, a rewrite of your server-side API logic could be helpful on the long run.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search