Eugene Sukh
Eugene Sukh

Reputation: 2737

Handling data values filter(JS)

I have a table, that I need to filter

Here is snippet

$(document).ready(function () {
    var $rows = $('tbody#report tr')
   
     var $filters = $('.table-filter').change(function(){
       var filterArr = $filters.filter(function(){
          return this.value
       }).map(function(){
          var $el = $(this);
          var value = $el.is('select') ? $el.find(':selected').text() :$el.val()  
          return {
            col: $el.data('col'),
            value: value.toLowerCase()
          }
       }).get();
       if(!filterArr.length){
         $rows.show()
       }else{
         $rows.hide().filter(function(){
            var $row = $(this)
            return filterArr.every(function(filterObj, i){
               var cellText = $row.find('td').eq(filterObj.col).text().toLowerCase();             
              return  cellText.includes(filterObj.value);
            })
         }).show()
       }
     })
   

});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/moment/moment/2.2.1/min/moment.min.js"></script>

<div class="row">
        <div class="col-md-3">
            <h4>Date from</h4>
            <input type="date" class="table-filter form-control" id="datefilterfrom" data-date-split-input="true"  data-col="1">
        </div>
        <div class="col-md-3">
            <h4>Date to</h4>
            <input type="date"  class="table-filter form-control" id="datefilterto" data-date-split-input="true">
        </div>
        <div class="col-md-2">
            <h4>Project</h4>
           <select id="projectfilter" name="projectfilter" class="table-filter form-control" data-col="2">
             <option value="">Select one</option>
             <option value="1">Test project</option><option value="2">Test2</option></select>
        </div>
     <div class="col-md-2">
            <h4>Service</h4>
           <select id="servicefilter" name="servicefilter" class="table-filter form-control"  data-col="3">
             <option value="">Select one</option>
             <option value="1">Test service</option><option value="2">Test2 service</option></select>
        </div>
    </div>
<table id="testTable" class="table">
            <thead>
                <tr>
                    <th scope="col">#</th>
                    <th scope="col">Date</th>
                    <th scope="col">Project</th>
                   <th scope="col">Service</th>
               
                </tr>
            </thead>
            <tbody id="report">
              <tr>
                <td class="proposalId">9</td><td> 17/07/2018</td> <td> Test project</td><td> Test service</td>
              </tr>
              <tr><td class="proposalId">8</td><td> 18/07/2018</td><td> Test project</td><td> Test2  service</td></tr>
              <tr><td class="proposalId">7</td><td> 17/07/2018</td><td> Test2</td><td> Test2 service</td></tr>
              <tr style=""><td class="proposalId">3</td><td> 19/07/2018</td><td> Test2</td><td> Test service</td></tr>
              
    </tbody>
        </table>

It works great with text searches, it's 3 and 4 selectfields, but I cannot handle the date.

I was trying to do it like this

 var value = $el.is('select') ? $el.find(':selected').text() : moment($el.val(), "YYYY-MM-DD").format('DD/MM/YYYY')

But it not works correctly. How I can solve it?

Here is my demo codepen snippet, you can use to test it

Upvotes: 1

Views: 74

Answers (2)

cнŝdk
cнŝdk

Reputation: 32145

Well there are many things to correct in your code:

  • The logic you are using to filter the data in the table is wrong, if an input value is changed the whole filter is reset taking only only this input value into account, you need to change the logic behind that.
  • For example for getting a select value you just need $el.val() instead of writing $el.is('select') ? $el.find(':selected').text() :$el.val().

And you need to handle dates separately in your filter code, because .includes() will be comparing strings, so you need to calculate and compare date objects here.

This is how should be your date comparison code:

if ($el.prop('type') == 'date') {
  return filterArr.every(function(filterObj, i) {
    var cellText = $row.find('td').eq(filterObj.col).text().toLowerCase();
    if ($el.prop('id') == "datefilterfrom") {
      return new Date(filterObj.value) <= new Date(cellText.split("/")[2], +cellText.split("/")[1] - 1, cellText.split("/")[0]);
    }
    if ($el.prop('id') == "datefilterto") {
      return new Date(filterObj.value) >= new Date(cellText.split("/")[2], +cellText.split("/")[1] - 1, cellText.split("/")[0]);
    }
  })
}

Note:

For the date inputs you need to pass 1 as col value in your filter object because you have only one date column in your table:

if ($el.prop('type') == 'date') {
    return {
      col: 1,
      value: value.toLowerCase()
    }
}

Demo:

This is an updated working demo.

$(document).ready(function() {
  var $rows = $('tbody#report tr')

  var $filters = $('.table-filter').change(function() {
    var $el = $(this);
    var filterArr = $filters.filter(function() {
      return this.value
    }).map(function() {
      var value = $el.val();
      if ($el.prop('type') == 'date') {
        return {
          col: 1,
          value: value.toLowerCase()
        }
      }
      return {
        col: $el.data('col'),
        value: value.toLowerCase()
      }
    }).get();
    if (!filterArr.length) {
      $rows.show()
    } else {
      $rows.hide().filter(function() {
        var $row = $(this);
        if ($el.prop('type') == 'date') {
          return filterArr.every(function(filterObj, i) {
            var cellText = $row.find('td').eq(filterObj.col).text().toLowerCase();
            if ($el.prop('id') == "datefilterfrom") {
              return new Date(filterObj.value) <= new Date(cellText.split("/")[2], +cellText.split("/")[1] - 1, cellText.split("/")[0]);
            }
            if ($el.prop('id') == "datefilterto") {
              return new Date(filterObj.value) >= new Date(cellText.split("/")[2], +cellText.split("/")[1] - 1, cellText.split("/")[0]);
            }
          })
        } else {
          return filterArr.every(function(filterObj, i) {
            var cellText = $row.find('td').eq(filterObj.col).text().toLowerCase();
            return cellText.includes(filterObj.value);
          })
        }
      }).show()
    }
  })


});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/moment/moment/2.2.1/min/moment.min.js"></script>

<div class="row">
  <div class="col-md-3">
    <h4>Date from</h4>
    <input type="date" class="table-filter form-control" id="datefilterfrom" data-date-split-input="true" data-col="1">
  </div>
  <div class="col-md-3">
    <h4>Date to</h4>
    <input type="date" class="table-filter form-control" id="datefilterto" data-date-split-input="true">
  </div>
  <div class="col-md-2">
    <h4>Project</h4>
    <select id="projectfilter" name="projectfilter" class="table-filter form-control" data-col="2">
      <option value="">Select one</option>
      <option value="1">Test project</option>
      <option value="2">Test2</option>
    </select>
  </div>
  <div class="col-md-2">
    <h4>Service</h4>
    <select id="servicefilter" name="servicefilter" class="table-filter form-control" data-col="3">
      <option value="">Select one</option>
      <option value="1">Test service</option>
      <option value="2">Test2 service</option>
    </select>
  </div>
</div>
<table id="testTable" class="table">
  <thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col">Date</th>
      <th scope="col">Project</th>
      <th scope="col">Service</th>

    </tr>
  </thead>
  <tbody id="report">
    <tr>
      <td class="proposalId">9</td>
      <td> 17/07/2018</td>
      <td> Test project</td>
      <td> Test service</td>
    </tr>
    <tr>
      <td class="proposalId">8</td>
      <td> 18/07/2018</td>
      <td> Test project</td>
      <td> Test2 service</td>
    </tr>
    <tr>
      <td class="proposalId">7</td>
      <td> 17/07/2018</td>
      <td> Test2</td>
      <td> Test2 service</td>
    </tr>
    <tr style="">
      <td class="proposalId">3</td>
      <td> 19/07/2018</td>
      <td> Test2</td>
      <td> Test service</td>
    </tr>

  </tbody>
</table>

Upvotes: 2

Alexey Kolotsey
Alexey Kolotsey

Reputation: 76

Try this

var value = $el.is('select') ? $el.find(':selected').text() : moment($el.val().replace(/(\d{2})\/(\d{2})\/(\d{4}).*/, '$3-$2-$1'), "YYYY-MM-DD").format('DD/MM/YYYY')

for example

 document.write(("17/07/2018").replace(/(\d{2})\/(\d{2})\/(\d{4}).*/, '$3-$2-$1'))

Upvotes: 0

Related Questions