0

I am having issues sorting multiple columns. I have one column working(experience) but cannot get the others as well. When i click on the column name i want the column to sort by name/number

Here is my app.js:

class App extends Component {     
    this.state = {
      applications: [{
        "id":1, "name":"John Smith", "position":"Server", "applied":"03/15/16", "experience":2, "availability":{
        "M":2, "T":2, "W":1, "Th":2, "F":1, "S":0,
        "Su":0 }, "questions":[
        {
        "text":"Have you ever been convicted of a felony?", "answer":"No" } ] }, 
        {
        "id":2, "name":"Jane Smith", "position":"Cook", "applied":"02/08/16", "experience":4, "availability":{
        "M":1, "T":1, "W":1, "Th":1, "F":0, "S":0, "Su":0 }, "questions":[
        {
        "text":"Have you ever been convicted of a felony?", "answer":"Yes" } ] }, 
        {
        "id":3, "name":"David Jessup", "position":"Chef", "applied":"03/08/16", "experience":2, "availability":{
        "M":2, "T":2, "W":2, "Th":2, "F":2,
        "S":0, "Su":0 }, "questions":[
        {
        "text":"Are you authorized to work in the United States?", "answer":"Yes" } ] }, 
        {
        "id":4, "name":"Clay van Schalkwijk", "position":"Cook", "applied":"03/08/16", "experience":1, "availability":{
        "M":1, "T":0, "W":1, "Th":0, "F":1, "S":0, "Su":0 }, "questions":[
        {
        "text":"Are you authorized to work in the United States?", "answer":"Yes" } ] }
        ],
        searchField:'',
        saved:[],
        direction: {
          name:'asc',
          position:'asc',
          experience: 'asc',
        }
    }
    this.sortBy = this.sortBy.bind(this)
  }
     onRemove = applicant => {
    const {saved} = this.state;
    saved.splice(saved.indexOf(applicant), 1);
    this.setState({
      saved
    })
  }
  sortBy = (key) => (
    this.setState({
      applications: this.state.applications.sort( (a, b) => (
        this.state.direction[key] === 'asc'
          ? parseFloat(a[key]) - parseFloat(b[key])
          : parseFloat(b[key]) - parseFloat(a[key]) 
      )),
      direction: {
        [key]: this.state.direction[key] === 'asc'
          ? 'desc'
          : 'asc'
      }
    })
  )
  render() {   
    return (
      <BrowserRouter>
      <div className='main'>
      <Sidebar/>
      <div className="App">
      <Search searchChange={this.onSearchChange}/>
      </div>
      <Switch>

        <Route exact path='/' render={()=> <Applications applications={this.state.applications} saved={this.state.saved} onRemove={this.onRemove} onFavorite={this.onFavorite} sortBy={this.sortBy}/>} />
        <Route path='/shortlistedApplicants' render={()=> <ShortlistedApplicants saved={this.state.saved} onRemove={this.onRemove} />}/>
        </Switch>
      </div>
      </BrowserRouter>
    );
  }
}

export default App;

Here is the component where the table is listed, the only column that will sort is the experience column:

    render(){
      console.log(this.props)
           return(
               <div>
               <Header applicationLen={this.props.applications.length} saved={this.props.saved} searchChange={this.props.onSearchChange}/>
            <div className='scroll'>
           <table className='app-table'>
                       <tr>
                    <th onClick={() => this.props.sortBy('name')}>Name</th>
              <th onClick={() => this.props.sortBy('position')}>Position</th>
                    <th onClick={() => this.props.sortBy('experience')}>Exp.</th>
                    <th>Question</th>
                    <th>Availability</th>
                    <th></th>
                    <th></th>
                    </tr>
                    {this.props.applications.map((app) => {
                        return(
                            <tr>
                            <td>{app.name}</td>
                         <td>{app.position}</td>
                         <td>{app.experience}</td>
                         <td>{app.questions[0].text} 
                         <p>
                         {app.questions[0].answer} </p>
                         </td>
                         <td><strong>M:</strong>{app.availability.M}, 
             <strong>T:</strong> {app.availability.T},
             <strong>W:</strong> {app.availability.W},
             <strong>Th:</strong> {app.availability.Th},
             <strong>F:</strong> {app.availability.F},
             <strong>S:</strong> {app.availability.S},
             <strong>Su:</strong> {app.availability.Su}</td>
     <td>Applied On: {app.applied}</td>
     <td><Btn onFavorite={() => this.props.onFavorite(app)} shortlist={this.props.saved.includes(app)}/></td>
                        </tr> )})}
                    </table>
                    </div>
           </div>
        )
    }
}

export default Applications;
Berheet
  • 79
  • 2
  • 11
  • I'd suggest beginning with rewriting the sorting function in a way that, instead of accepting just `key`, it accepts [any number of arguments](https://stackoverflow.com/questions/17943186/sort-an-array-of-objects-by-multiple-properties). And once it's done, think about the way the user would turn the sorting on columns on and off, priorities and such. – rishat Sep 25 '18 at 22:06

1 Answers1

2

As I can see from the code, it will only work for integer values, when you are passing string values to the sort function you actually need to compare the string

This code will work with any data type integrs or strings. ( Here "column" is key that you want to sort upon )

arraydata.sort(function(a, b){
    if(a.column < b.column) return -1;  // Ascending Order
    if(a.column > b.column) return 1;   // Descending Order  
    return 0; // Default
})

// To ignore case and with ES6 syntax simply put this,

arraydata.sort((a, b) => a.column.localeCompare(b.column))

Hope this will help

Alok Rai
  • 75
  • 9