How to Filter Data on a Webpage (with JavaScript)

Filtering is a commonly used feature on various webpages. It allows users to narrow down data (like categories, tags, other characteristics) using provided parameters. Let’s create our own!

One common example of on-page filtering would be an eCommerce website that allows users to filter products according to size, color, brand etc.

In this tutorial, we’ll be recreating the Tuts+ author page and implementing a filter component to allow us to filter articles based on their category. 

Data Filter Demo

Let’s take a look at what we’ll be building—click a filter tag in the demo to toggle the displayed tutorials:

For a CSS-only approach to filtering data on a webpage, check out this tutorial:

1. Layout and Styling

For this demo, we’ll be cloning the author page so the markup and styling is taken directly from the live site. The main components we’ll be focusing on are the filters and the displayed posts, so we’ll create a <div class="filter-container"> and <div class="posts-container"> and target these in JavaScript.

We’ll style these containers and their content in CSS:

1
.posts-container {
2
  display: flex;
3
  flex-wrap: wrap;
4
}
5

6
.post {
7
  position: relative;
8
  width: 300px;
9
  margin-right: 30px;
10
  margin-bottom: 40px;
11
  border: 1px solid #e1e8ed;
12
  border-radius: 4px;
13
  margin-top: 13px;
14
  min-height: 300px;
15
  height: auto;
16
}
17

18
.filter-container {
19
  display: flex;
20
  flex-wrap: wrap;
21
  justify-content: flex-start;
22
  gap: 10px;
23
  padding: 32px 0;
24
  border-top: 1px solid #e4e4e4;
25
  border-bottom: 1px solid #e4e4e4;
26
  margin-bottom: 32px;
27
}
28

29
.filter-button {
30
  transition: background-color 200ms, color 200ms;
31
  background-color: transparent;
32
  font: inherit;
33
  cursor: pointer;
34
  display: inline-block;
35
  padding: 0 8px;
36
  color: #717171;
37
  border: 1px solid #9b9b9b;
38
  border-radius: 25px;
39
  font-size: 14px;
40
  white-space: nowrap;
41
}
42

43
.filter-button:hover {
44
  background-color: #f3f3f3;
45
  color: #3a3a3a;
46
}
47

48
.filter-button.is-active {
49
  background-color: #0085b6;
50
  border-color: #0085b6;
51
  color: #fff;
52
}

2. Getting Page Data using Fetch API

In this demo, we’ll be using the Fetch API to retrieve mock data scraped from the Tuts+ authors page and stored in a Github gist.

Our mock data has the format:

1
[
2
  {
3
    "title": "",
4
    "link": "",
5
    "image": "",
6
    "categories": [ ]
7
  },
8
  ...
9
]
10
  

This is the script for fetching data from the script:

1
fetch("https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials"
2
).then(async (response) => {
3
  // handle response data

4
});

Once we’ve gotten our fetched data, we can then manipulate the data and append it on the page.

3. Appending Data to the Webpage

For each object in our fetched response, we’ll create a post div that will display the data on the page. First, let’s define our global variables:

1
let postsData = "";
2
const postsContainer = document.querySelector(".posts-container");

Then we’ll create a function createPost() that will handle appending a new div to the posts-container element. In this function, we create a new div element with the classname post and set its innerHTML as the data we want to display.

1
const createPost = (postData) => {
2
  const { title, link, image, categories } = postData;
3
  const post = document.createElement("div");
4
  post.className = "post";
5
  post.innerHTML = `

6
      <a class="post-preview" href="${link}" target="_blank">

7
        <img class="post-image" src="${image}">

8
      </a>

9
      <div class="post-content">

10
        <p class="post-title">${title}</p>

11
        <div class="post-tags">

12
          ${categories
13
            .map((category) => {
14
              return '<span class="post-tag">' + category + "</span>";
15
            })
16
            .join("")}

17
        </div>

18
      </div>

19
  `;
20

21
  postsContainer.append(post);
22
};

Inside our post innerHTML, we use the join("") method on our categories.map() to remove the ‘,’ symbol that’s included in every array.

Now we can update our response function to call the createPost() function once the data has been fetched:

1
fetch("https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials"
2
).then(async (response) => {
3
  postsData = await response.json();
4
  postsData.map((post) => createPost(post));
5
});

4. Get Filter Params from Response

Since we’re using JavaScript, we can map through our response to create a dynamic list of filter params. Let’s include the global variables for our filter data:

1
let filterData = "";
2
const filterContainer = document.querySelector(".filter-container");

Now we want to write a script that sorts through the categories array in each response object and returns a unique list. We can update our response object to handle getting a unique list of filter params

1
fetch("https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials"
2
).then(async (response) => {
3
  postsData = await response.json();
4
  postsData.map((post) => createPost(post));
5
  filterData = [
6
    ...new Set(
7
      postsData
8
        .map((post) => post.categories)
9
        .reduce((acc, curVal) => acc.concat(curVal), [])
10
    )
11
  ];
12
});

Breaking down the code for our filterData:

  • We use [... new Set] to create an array of unique values. Set returns an object of unique values and the spread syntax […] converts the object into an array.
  • We map through the postsData to get the categories array of each post object inside the data response.
  • We use the .reduce() method to combine the categories array for each post object into one array.

Once we’ve gotten our array of unique filter values from the post categories, we can create a function to append each filter to the page. We’ll create a new button element and set the innerText and className. We’ll also set a “data-state” attribute to handle changing the button state when clicked.

Each filter button will have a click event listener set to the handleButtonClick function, which will be responsible for handling the filtering logic.

1
const createFilter = (filter) => {
2
  const filterButton = document.createElement("button");
3
  filterButton.className = "filter-button";
4
  filterButton.innerText = filter;
5
  filterButton.setAttribute('data-state', 'inactive');
6
  filterButton.addEventListener("click", (e) =>
7
    handleButtonClick(e, filter)
8
  );
9

10
  filterContainer.append(filterButton);
11
};

And update our response function to call the createFilter() function:

1
fetch("https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials"
2
).then(async (response) => {
3
  postsData = await response.json();
4
  postsData.map((post) => createPost(post));
5
  filterData = [
6
    ...new Set(
7
      postsData
8
        .map((post) => post.categories)
9
        .reduce((acc, curVal) => acc.concat(curVal), [])
10
    )
11
  ];
12
  filterData.map((filter) => createFilter(filter));
13
});

5. Handle Filtering when Clicked

Now we’ve gotten our filter buttons and initial data, we can define a function to handle filtering the data when a button is clicked. This can be done using the .filter() method on the posts data array.

This is the logic we’ll use for filtering the data:

  • Create a function handleFilterPosts() that accepts a filter param
  • Use the .filter() method to filter our posts data based on the filter param
  • Clear all elements in posts-container and append the new filteredData to the container.
1
const handleFilterPosts = (param) => {
2
  let filteredPosts = [...postsData].filter(post => post.categories.includes(param))
3
  
4
  postsContainer.innerHTML = "";
5
  filteredPosts.map(post => createPost(post))
6
};

We want to detect when a button has been clicked and update the button state. In this tutorial, we’ll toggle the buttons so if clicked once, the button is set to active and if clicked again, the button is set to inactive.

1
const handleButtonClick = (e, param) => {
2
  const button = e.target;
3
  const buttonState = button.getAttribute('data-state');
4
  
5
  if (buttonState =='inactive') {
6
    button.classList.add('is-active');
7
    button.setAttribute('data-state', 'active');
8
  } else {
9
    button.classList.remove('is-active');
10
    button.setAttribute('data-state', 'inactive')
11
  }
12
}

We also want to make sure only one button is selected at a time and if no button is selected, the posts should display the default data so we can create functions to handle that logic:

1
const resetFilterButtons = (currentButton) => {
2
  const filterButtons = document.querySelectorAll('.filter-button');
3
  [...filterButtons].map(button => {
4
    if (button != currentButton) {
5
      button.classList.remove('is-active');
6
      button.setAttribute('data-state', 'inactive')
7
    }
8
  })
9
}
10

11
const resetPosts = () => {
12
  postsContainer.innerHTML = "";
13
  postsData.map((post) => createPost(post));
14
}

Finally, we can update our button click function:

1
const handleButtonClick = (e, param) => {
2
  const button = e.target;
3
  const buttonState = button.getAttribute('data-state');
4
  resetFilterButtons(button);
5
  
6
  if (buttonState =='inactive') {
7
    button.classList.add('is-active');
8
    button.setAttribute('data-state', 'active');
9
    handleFilterPosts(param)
10
  } else {
11
    button.classList.remove('is-active');
12
    button.setAttribute('data-state', 'inactive')
13
    resetPosts()
14
  }
15
}

Conclusion

And with that, we’ve completely built a filtering component for data on a webpage using vanilla JavaScript!


This content originally appeared on Envato Tuts+ Tutorials and was authored by Jemima Abu

Filtering is a commonly used feature on various webpages. It allows users to narrow down data (like categories, tags, other characteristics) using provided parameters. Let’s create our own!

One common example of on-page filtering would be an eCommerce website that allows users to filter products according to size, color, brand etc.

In this tutorial, we’ll be recreating the Tuts+ author page and implementing a filter component to allow us to filter articles based on their category. 

Data Filter Demo

Let’s take a look at what we’ll be building—click a filter tag in the demo to toggle the displayed tutorials:

For a CSS-only approach to filtering data on a webpage, check out this tutorial:

1. Layout and Styling

For this demo, we’ll be cloning the author page so the markup and styling is taken directly from the live site. The main components we’ll be focusing on are the filters and the displayed posts, so we’ll create a <div class="filter-container"> and <div class="posts-container"> and target these in JavaScript.

We’ll style these containers and their content in CSS:

1
.posts-container {
2
  display: flex;
3
  flex-wrap: wrap;
4
}
5
6
.post {
7
  position: relative;
8
  width: 300px;
9
  margin-right: 30px;
10
  margin-bottom: 40px;
11
  border: 1px solid #e1e8ed;
12
  border-radius: 4px;
13
  margin-top: 13px;
14
  min-height: 300px;
15
  height: auto;
16
}
17
18
.filter-container {
19
  display: flex;
20
  flex-wrap: wrap;
21
  justify-content: flex-start;
22
  gap: 10px;
23
  padding: 32px 0;
24
  border-top: 1px solid #e4e4e4;
25
  border-bottom: 1px solid #e4e4e4;
26
  margin-bottom: 32px;
27
}
28
29
.filter-button {
30
  transition: background-color 200ms, color 200ms;
31
  background-color: transparent;
32
  font: inherit;
33
  cursor: pointer;
34
  display: inline-block;
35
  padding: 0 8px;
36
  color: #717171;
37
  border: 1px solid #9b9b9b;
38
  border-radius: 25px;
39
  font-size: 14px;
40
  white-space: nowrap;
41
}
42
43
.filter-button:hover {
44
  background-color: #f3f3f3;
45
  color: #3a3a3a;
46
}
47
48
.filter-button.is-active {
49
  background-color: #0085b6;
50
  border-color: #0085b6;
51
  color: #fff;
52
}

2. Getting Page Data using Fetch API

In this demo, we'll be using the Fetch API to retrieve mock data scraped from the Tuts+ authors page and stored in a Github gist.

Our mock data has the format:

1
[
2
  {
3
    "title": "",
4
    "link": "",
5
    "image": "",
6
    "categories": [ ]
7
  },
8
  ...
9
]
10
  

This is the script for fetching data from the script:

1
fetch("https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials"
2
).then(async (response) => {
3
  // handle response data

4
});

Once we’ve gotten our fetched data, we can then manipulate the data and append it on the page.

3. Appending Data to the Webpage

For each object in our fetched response, we’ll create a post div that will display the data on the page. First, let’s define our global variables:

1
let postsData = "";
2
const postsContainer = document.querySelector(".posts-container");

Then we’ll create a function createPost() that will handle appending a new div to the posts-container element. In this function, we create a new div element with the classname post and set its innerHTML as the data we want to display.

1
const createPost = (postData) => {
2
  const { title, link, image, categories } = postData;
3
  const post = document.createElement("div");
4
  post.className = "post";
5
  post.innerHTML = `

6
      <a class="post-preview" href="${link}" target="_blank">

7
        <img class="post-image" src="${image}">

8
      </a>

9
      <div class="post-content">

10
        <p class="post-title">${title}</p>

11
        <div class="post-tags">

12
          ${categories
13
            .map((category) => {
14
              return '<span class="post-tag">' + category + "</span>";
15
            })
16
            .join("")}

17
        </div>

18
      </div>

19
  `;
20
21
  postsContainer.append(post);
22
};

Inside our post innerHTML, we use the join("") method on our categories.map() to remove the ',' symbol that’s included in every array.

Now we can update our response function to call the createPost() function once the data has been fetched:

1
fetch("https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials"
2
).then(async (response) => {
3
  postsData = await response.json();
4
  postsData.map((post) => createPost(post));
5
});

4. Get Filter Params from Response

Since we’re using JavaScript, we can map through our response to create a dynamic list of filter params. Let’s include the global variables for our filter data:

1
let filterData = "";
2
const filterContainer = document.querySelector(".filter-container");

Now we want to write a script that sorts through the categories array in each response object and returns a unique list. We can update our response object to handle getting a unique list of filter params

1
fetch("https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials"
2
).then(async (response) => {
3
  postsData = await response.json();
4
  postsData.map((post) => createPost(post));
5
  filterData = [
6
    ...new Set(
7
      postsData
8
        .map((post) => post.categories)
9
        .reduce((acc, curVal) => acc.concat(curVal), [])
10
    )
11
  ];
12
});

Breaking down the code for our filterData:

  • We use [... new Set] to create an array of unique values. Set returns an object of unique values and the spread syntax [...] converts the object into an array.
  • We map through the postsData to get the categories array of each post object inside the data response.
  • We use the .reduce() method to combine the categories array for each post object into one array.

Once we’ve gotten our array of unique filter values from the post categories, we can create a function to append each filter to the page. We’ll create a new button element and set the innerText and className. We’ll also set a “data-state” attribute to handle changing the button state when clicked.

Each filter button will have a click event listener set to the handleButtonClick function, which will be responsible for handling the filtering logic.

1
const createFilter = (filter) => {
2
  const filterButton = document.createElement("button");
3
  filterButton.className = "filter-button";
4
  filterButton.innerText = filter;
5
  filterButton.setAttribute('data-state', 'inactive');
6
  filterButton.addEventListener("click", (e) =>
7
    handleButtonClick(e, filter)
8
  );
9
10
  filterContainer.append(filterButton);
11
};

And update our response function to call the createFilter() function:

1
fetch("https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials"
2
).then(async (response) => {
3
  postsData = await response.json();
4
  postsData.map((post) => createPost(post));
5
  filterData = [
6
    ...new Set(
7
      postsData
8
        .map((post) => post.categories)
9
        .reduce((acc, curVal) => acc.concat(curVal), [])
10
    )
11
  ];
12
  filterData.map((filter) => createFilter(filter));
13
});

5. Handle Filtering when Clicked

Now we’ve gotten our filter buttons and initial data, we can define a function to handle filtering the data when a button is clicked. This can be done using the .filter() method on the posts data array.

This is the logic we’ll use for filtering the data:

  • Create a function handleFilterPosts() that accepts a filter param
  • Use the .filter() method to filter our posts data based on the filter param
  • Clear all elements in posts-container and append the new filteredData to the container.
1
const handleFilterPosts = (param) => {
2
  let filteredPosts = [...postsData].filter(post => post.categories.includes(param))
3
  
4
  postsContainer.innerHTML = "";
5
  filteredPosts.map(post => createPost(post))
6
};

We want to detect when a button has been clicked and update the button state. In this tutorial, we’ll toggle the buttons so if clicked once, the button is set to active and if clicked again, the button is set to inactive.

1
const handleButtonClick = (e, param) => {
2
  const button = e.target;
3
  const buttonState = button.getAttribute('data-state');
4
  
5
  if (buttonState =='inactive') {
6
    button.classList.add('is-active');
7
    button.setAttribute('data-state', 'active');
8
  } else {
9
    button.classList.remove('is-active');
10
    button.setAttribute('data-state', 'inactive')
11
  }
12
}

We also want to make sure only one button is selected at a time and if no button is selected, the posts should display the default data so we can create functions to handle that logic:

1
const resetFilterButtons = (currentButton) => {
2
  const filterButtons = document.querySelectorAll('.filter-button');
3
  [...filterButtons].map(button => {
4
    if (button != currentButton) {
5
      button.classList.remove('is-active');
6
      button.setAttribute('data-state', 'inactive')
7
    }
8
  })
9
}
10
11
const resetPosts = () => {
12
  postsContainer.innerHTML = "";
13
  postsData.map((post) => createPost(post));
14
}

Finally, we can update our button click function:

1
const handleButtonClick = (e, param) => {
2
  const button = e.target;
3
  const buttonState = button.getAttribute('data-state');
4
  resetFilterButtons(button);
5
  
6
  if (buttonState =='inactive') {
7
    button.classList.add('is-active');
8
    button.setAttribute('data-state', 'active');
9
    handleFilterPosts(param)
10
  } else {
11
    button.classList.remove('is-active');
12
    button.setAttribute('data-state', 'inactive')
13
    resetPosts()
14
  }
15
}

Conclusion

And with that, we’ve completely built a filtering component for data on a webpage using vanilla JavaScript!


This content originally appeared on Envato Tuts+ Tutorials and was authored by Jemima Abu


Print Share Comment Cite Upload Translate Updates
APA

Jemima Abu | Sciencx (2022-09-30T21:45:59+00:00) How to Filter Data on a Webpage (with JavaScript). Retrieved from https://www.scien.cx/2022/09/30/how-to-filter-data-on-a-webpage-with-javascript/

MLA
" » How to Filter Data on a Webpage (with JavaScript)." Jemima Abu | Sciencx - Friday September 30, 2022, https://www.scien.cx/2022/09/30/how-to-filter-data-on-a-webpage-with-javascript/
HARVARD
Jemima Abu | Sciencx Friday September 30, 2022 » How to Filter Data on a Webpage (with JavaScript)., viewed ,<https://www.scien.cx/2022/09/30/how-to-filter-data-on-a-webpage-with-javascript/>
VANCOUVER
Jemima Abu | Sciencx - » How to Filter Data on a Webpage (with JavaScript). [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/09/30/how-to-filter-data-on-a-webpage-with-javascript/
CHICAGO
" » How to Filter Data on a Webpage (with JavaScript)." Jemima Abu | Sciencx - Accessed . https://www.scien.cx/2022/09/30/how-to-filter-data-on-a-webpage-with-javascript/
IEEE
" » How to Filter Data on a Webpage (with JavaScript)." Jemima Abu | Sciencx [Online]. Available: https://www.scien.cx/2022/09/30/how-to-filter-data-on-a-webpage-with-javascript/. [Accessed: ]
rf:citation
» How to Filter Data on a Webpage (with JavaScript) | Jemima Abu | Sciencx | https://www.scien.cx/2022/09/30/how-to-filter-data-on-a-webpage-with-javascript/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.