Reputation: 105
I created a function to sort a state array of objects according to one of the key: value pairs. Here's what it looks like: It's currently working.
State:
class Employee extends Component {
state = {
employeeData: [],
filteredEmployeeData: [],
search: '',
sort: 'asc',
error: '',
}
Working function:
sortFirstName = () => {
console.log('SORTING!!!!')
const {employeeData} = this.state
const sorted = employeeData.sort((a, b) => {
if (a.name.first < b.name.first){
return -1
} else if (a.name.first > b.name.first){
return 1
} else {
return 0
}
})
console.log('Sorted List: ', sorted)
this.setState({filteredEmployeeData: sorted})
}
Render:
render () {
return (
<div>
<Container style={{ minHeight: "80%" }}>
<br/>
<h1 className="text-center">Search For An Employee</h1>
<Alert
type="danger"
style={{ opacity: this.state.error ? 1 : 0, marginBottom: 10 }}
>
{this.state.error}
</Alert>
<SearchForm
handleInputChange={this.handleInputChange}
search={this.state.search}
/>
</Container>
<Container>
<table className="table table-hover">
<thead>
<tr>
<th scope="col" >Image</th>
<th scope="col" value="firstName" onClick={(this.sortFirstName)}>First Name</th>
<th scope="col" value="lastName">Last Lame</th>
<th scope="col" value="email">Email</th>
<th scope="col" value="phoneNumber">Phone Number</th>
<th scope="col" value="city">City</th>
<th scope="col" value="SSN">SSN</th>
</tr>
</thead>
<tbody>
{this.state.filteredEmployeeData.map(ee => (
<EmployeeData
id={ee.login.uuid}
key={ee.login.uuid}
img={ee.picture.thumbnail}
firstName={ee.name.first}
lastName={ee.name.last}
email={ee.email}
phone={ee.cell}
city={ee.location.city}
ssn={ee.id.value}
/>
))}
</tbody>
</table>
</Container>
</div>
);
}}
What I'd like to do is update the function to be dynamic so that any of my table headers can be clicked and the data will sort accordingly. I tried it as something like this but I can't quite figure out a way to do it.
My attempt at creating a dynamic sort function (doesn't work):
sort = (header) => {
console.log('SORTING!!!!')
const {employeeData} = this.state
const sorted = employeeData.sort((a, b) => {
if (a.header < b.header){
return -1
} else if (a.header > b.header){
return 1
} else {
return 0
}
})
console.log('Sorted List: ', sorted)
this.setState({filteredEmployeeData: sorted})
}
Render with dynamic sorts (doesn't work)
<thead>
<tr>
<th scope="col" >Image</th>
<th scope="col" value="firstName" onClick={(this.sort('name.first')}>First Name</th>
<th scope="col" value="lastName" onClick={(this.sort('name.last')}>Last Lame</th>
<th scope="col" value="email" onClick={(this.sort('email')}>Email</th>
<th scope="col" value="phoneNumber" onClick={(this.sort('cell')}>Phone Number</th>
<th scope="col" value="city" onClick={(this.sort('city')}>City</th>
<th scope="col" value="SSN" onClick={(this.sort('ssn')}>SSN</th>
</tr>
</thead>
Any help here would be appreciated.
Upvotes: 2
Views: 76
Reputation: 1396
For "name.first" and "name.last", there is a little bit of work. You need to make it into a single word to access it. For nested object I prefer this solution from this post:
function fetchFromObject(obj, prop) {
if(typeof obj === 'undefined') {
return false;
}
var _index = prop.indexOf('.')
if(_index > -1) {
return fetchFromObject(obj[prop.substring(0, _index)], prop.substr(_index + 1));
}
return obj[prop];
}
sort = (header) => {
console.log('SORTING!!!!')
const {employeeData} = this.state
const sorted = employeeData.sort((a, b) => {
const x = fetchFromObject(a, header);
const y = fetchFromObject(b, header);
if (x < y){
return -1
} else if (x > y){
return 1
} else {
return 0
}
})
console.log('Sorted List: ', sorted)
this.setState({filteredEmployeeData: sorted})
}
Upvotes: 1
Reputation: 798
As per my understanding you want something like this.
This is dynamic sorting with the string dot notation accessing the object
sort = (header) => {
const {employeeData} = this.state;
const sorted = employeeData.sort((a, b) => {
a = getDescendantProp(a, header);
b = getDescendantProp(b, header);
if (a < b){
return -1
} else if (a> b){
return 1
} else {
return 0
}
})
console.log('Sorted List: ', sorted)
this.setState({filteredEmployeeData: sorted})
}
function getDescendantProp(obj, desc) {
var arr = desc.split(".");
while(arr.length && (obj = obj[arr.shift()]));
return obj;
}
Upvotes: 0