Search JS array without losing index - Working Codepen Demo uses fetch() and Alpine.js

Viewed 279

I have a working CodePen demo here: https://codepen.io/JosephAllen/pen/vYmQpWL?editors=0010

This demo:

  1. Fetches users from an API
  2. Sorts the list based on a "points" property
  3. And then displays that sorted list utilizing the index as a "rank". In other words, if your index is zero, you're in first place.

There is an input field to search and filter the list, but filtering the array creates a new index for each user – which ruins the whole idea of a rank.

How can I keep the rank and search feature without creating new indexes for users?

If I was the author of the API I would just include the rank as a property, but I'm not.

My fetch function:

getUsers() {
    fetch(`https://trafficthinktank.com/wp-json/mjtw/v1/community`)
        .then((res) => res.json())
        .then((data) => {
            this.isLoading = false;
            this.users = data.sort((a, b) => b.points - a.points);
            // this.users = this.users.map(user => ({ visible: true, ...user }));
            console.log(this.users);
        });
    0;
}

My filter function:

get filteredUsers() {
    if (this.search === "") {
        return this.users;
    }

    return this.users.filter((item) => {
        return item.name.toLowerCase().includes(this.search.toLowerCase());
    });
}
1 Answers

Indexes can not remain constant since there can't be an array with missing number in its index sequence. Nevertheless, you can simply map your array and keep indexes inside. Look at this, might be helpful:

getUsers() {
    fetch(`https://trafficthinktank.com/wp-json/mjtw/v1/community`)
        .then((res) => res.json())
        .then((data) => {
            this.isLoading = false;
            this.users = data.sort((a, b) => b.points - a.points);
            // this.users = this.users.map(user => ({ visible: true, ...user }));
            this.users = this.users.map((entity, index) => ({index, entity}));
            console.log(this.users);
        });
    0;
}

and then you can filter like this

get filteredUsers() {
    if (this.search === "") {
        return this.users;
    }

    return this.users.filter((item) => {
        return item.entity.name.toLowerCase().includes(this.search.toLowerCase());
    });
}
Related