ComCool
ComCool

Reputation: 1103

React with sort and filter

I'm still new in React. I get some data from a JSON file. I managed to get the search to work. But I also want to be able to click my name table header and filter my data by name. How do I make that work with filter.

import React, { PropTypes } from 'react';

// Mock Data
let MockData = require('./generated.json');
let searchValue = '';

export default class Employees extends React.PureComponent {

  constructor(props) {
    super(props);
    this.state = {
      searchValue: '',
      sortValue: null
    };

    this.searchInputChange = this.searchInputChange.bind(this);
    this.searchSubmit = this.searchSubmit.bind(this);
  }

  // Sort function
  sortFunction(sortValue, event) {
    alert(sortValue);
    this.setState({sortValue: sortValue});
  }

  // Update search value state function
  searchInputChange(event) {
     this.searchValue = event.target.value;
   }

  // Search function
  searchSubmit(event) {
    this.setState({searchValue: this.searchValue});
  }



  render() {

    let sortedEmployeesBySearch = MockData.filter(
      (employee) => {
        // If state searchValue is not null
        if (this.state.searchValue) {
          return employee.name.indexOf(this.state.searchValue) !== -1 || employee.gender.indexOf(this.state.searchValue) !== -1 || employee.company.indexOf(this.state.searchValue) !== -1 || employee.email.indexOf(this.state.searchValue) !== -1;
        }
        else {
          return employee;
        }
      }
    );

    return (
      <div className="container">
          <input className="search" type="text" name="search" placeholder="Search table" onChange={this.searchInputChange} />
          <input className="searchButton" type="button" value="Search" onClick={this.searchSubmit} />
        <table className="employeesList">
          <thead>
            <tr>
              <th onClick={this.sortFunction.bind(this,'name')}>Name</th>
              <th onClick={this.sortFunction.bind(this,'gender')}>Gender</th>
              <th onClick={this.sortFunction.bind(this,'company')}>Company</th>
              <th onClick={this.sortFunction.bind(this,'email')}>E-mail</th>
            </tr>
          </thead>
          <tbody>
            { sortedEmployeesBySearch.map((employee) => (
            <tr key={employee.id}>
              <td>{employee.name}</td>
              <td>{employee.gender}</td>
              <td>{employee.company}</td>
              <td>{employee.email}</td>
            </tr>
            ))}
          </tbody>
        </table>
      </div>
    );

  }

}

Upvotes: 1

Views: 5815

Answers (1)

Louie Anderson
Louie Anderson

Reputation: 181

You can sort the data by: 1) Storing in state the property to sort on, which you are already doing 2) Chaining a sort function after the filter of your MockData

The second task can be accomplished by:

MockData.filter(...).sort((a, b) => {
   aVal = a[this.state.sortValue];
   bVal = b[this.state.sortValue];
   switch(typeof aVal) {
      case 'string':
         return aVal.localeCompare(bVal);
      case 'number':
         return aVal - bVal;
      default:
         throw new Error("Unsupported value to sort by");
   }
});

You can even pass a custom function into the sort method that takes the two values and does custom sorting logic based on the sortValue property.

Upvotes: 3

Related Questions