最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - ReactJS with Material-UI: How to sort an array of Material-UI's <TableRow> alphabetically? -

programmeradmin4浏览0评论

Currently, I render Material-UI's <Table>'s <TableRow> () with an array of <TableRow>s and by using .map(). Each <TableRow> has a <TableRowColumn> that represents a first name, like so <TableRowColumn>Josh</TableRowColumn>.

But, if a user presses a button, I would like to sort the <TableRow> array alphabetically by the <TableRowColumn>'s first name. So say for example out of 10 <TableRow>s, if the array[0] had a first name Conny and array[1] had Adrian, would like the array[1] to bee array[0].

What would the right approach to this? Any guidance or insight would be greatly appreciated it.

EDIT

Each row would be rendered like so with the array rows, that has objects with properties firstName and favColor:

        {
          rows.map((row) => {
            return(
              <UserRow
                firstName={row.firstName}
                favColor={row.favColor}
              />
            )
          })
        }

And each row is defined like so:

const UserRow = (props) => {
  const {firstName, favColor} = props

  return (
    <TableRow>
      <TableRowColumn>{firstName}</TableRowColumn>
      <TableRowColumn>{favColor}</TableRowColumn>
    </TableRow>
  )
}

Currently, I render Material-UI's <Table>'s <TableRow> (http://www.material-ui./#/ponents/table) with an array of <TableRow>s and by using .map(). Each <TableRow> has a <TableRowColumn> that represents a first name, like so <TableRowColumn>Josh</TableRowColumn>.

But, if a user presses a button, I would like to sort the <TableRow> array alphabetically by the <TableRowColumn>'s first name. So say for example out of 10 <TableRow>s, if the array[0] had a first name Conny and array[1] had Adrian, would like the array[1] to bee array[0].

What would the right approach to this? Any guidance or insight would be greatly appreciated it.

EDIT

Each row would be rendered like so with the array rows, that has objects with properties firstName and favColor:

        {
          rows.map((row) => {
            return(
              <UserRow
                firstName={row.firstName}
                favColor={row.favColor}
              />
            )
          })
        }

And each row is defined like so:

const UserRow = (props) => {
  const {firstName, favColor} = props

  return (
    <TableRow>
      <TableRowColumn>{firstName}</TableRowColumn>
      <TableRowColumn>{favColor}</TableRowColumn>
    </TableRow>
  )
}
Share Improve this question edited Nov 13, 2016 at 3:38 asked Nov 11, 2016 at 5:32 user3259472user3259472
Add a ment  | 

2 Answers 2

Reset to default 6

I would sort the array before applying the map operation that will create the TableRows.

The react way of thinking is declarative. This means that on a visual level, you should provide the elements as they should be displayed. Hence they get sorted before they are passed to the view ponent.

For example (I couldn't use material-ui elements since the example didn't run in the stackoverflow setup. Just replace all elements of TableComponent with their material-ui alter ego.):

const data = [
  {firstname: "John", lastname: "Rover",  id:12},
  {firstname: "Bob",  lastname: "Taylor", id:24},
  {firstname: "Lucy", lastname: "Heart",  id:43}
]

// The table ponent is unaware of the data order operations
const TableComponent = ({tableData}) => <table><tbody>
  {tableData.map(d=> <tr key={d.id}>
      <td>{d.firstname}</td>
      <td>{d.lastname}</td>
  </tr>)}
</tbody></table>

// The parent ponent takes care of feeding the Table
// ponent with the data in the correct order.  
class App extends React.Component {
  state = { sortBy: "firstname"}
  handleChange = (event) => this.setState(
    {sortBy: event.target.value}
  );
  render () {
    const {data} = this.props; 
    const {sortBy} = this.state;
    const sortedData = data.sort((a,b) => a[sortBy]>b[sortBy]?1:-1)
    return <div>
      Sort by  
      <select value={sortBy} onChange={this.handleChange}>
        <option value="firstname">First Name</option>
        <option value="lastname">Last Name</option>
      </select>
      <h2>The table: </h2>
      <TableComponent tableData={sortedData} />
    </div>
  }
}
  
ReactDOM.render(
  <App data={data} />,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>

Here's a full example of an app with a table where its rows can be sorted by clicking on the header. Comments are inline and the full example is available here

The table's state contains the rows which are sorted whenever a table column header is clicked as well as the property name of the sorted column.

import React from 'react';
import { MuiThemeProvider} from 'material-ui';
import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui';

// properties of TableHeader ponent
let headerProps = {
  enableSelectAll: false,
  displaySelectAll: false,
  adjustForCheckbox: false
};

// initial set of rows, simulating data from the database
let rows = [
  {firstName: "Adrian", favColor: "gold", uniqueId: 0 },
  {firstName: "Alma", favColor: "green", uniqueId: 1 },
  {firstName: "Conny", favColor: "black", uniqueId: 2 },
  {firstName: "Jane", favColor: "blue", uniqueId: 3 }
];

// our table hader information, key is the name of the 
// property to sort by when the header is clicked 
let headers = [
  {name: "First Name", key: "firstName"},
  {name: "Favorite Color", key: "favColor"}
];


// our table ponent that can sort columns
class SortableTable extends React.Component {
  
  constructor(props){
    super(props);
    this.state = {rows, sortBy: 'firstName'};
  }

  renderHeaders(){
    let header= headers.map( (h) => {
      return <SortableHeader 
                key={h.key}
                name={h.name}
                onClicked={()=>this.updateSortBy(h.key)} 
                isSortColumn={this.state.sortBy == h.key}/>
    });
    return <TableRow>{header}</TableRow>;
  }
  
  renderRows() {
    return this.state.rows.map( (row, i) => <UserRow {...row} key={row.uniqueId}/> );
  }
                               
  updateSortBy(sortBy){
      // multiple clicks on the same column reverse the sort order
      if( sortBy == this.state.sortBy ){
        this.setState( {rows: [...this.state.rows.reverse()]} );
        return;
      }
      
      let rows = [...this.state.rows];
      rows.sort( (a,b) => {
        if (a[sortBy] < b[sortBy])
          return -1;
        if(a[sortBy] > b[sortBy])
          return 1;
        return 0;
      });
      
      this.setState({rows, sortBy});
    }

      
  render() {
    return (
        <MuiThemeProvider>
        <Table>
          <TableHeader {...headerProps}>
              {this.renderHeaders()}
          </TableHeader>
          <TableBody>
            {this.renderRows()}
          </TableBody>
        </Table>
      </MuiThemeProvider>
    );
  }
}

  
  
function SortableHeader(props){
  let style = {
    cursor: "pointer"
  }
  if(props.isSortColumn){
    style.fontWeight = "bold";
    style.color = "black";
  }
  
  return (
    <TableHeaderColumn>
      <div style={style} onClick={() => props.onClicked()}>{props.name}</div>
    </TableHeaderColumn>
  );
}
  

function UserRow(props){
  return (
    <TableRow>
      <TableRowColumn>{props.firstName}</TableRowColumn>
      <TableRowColumn>{props.favColor}</TableRowColumn>
    </TableRow>
  );
}

export default SortableTable;

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论