Codementor Events

Approach on FILTER structure and its general logic

Published Aug 18, 2019
Approach on FILTER structure and its general logic

A few month ago I worked on the filters for a cellphone company hotsale event. Before start coding, it is important to establish the general logic and structure of this development. In this article you will find an example on how to raise this issue.

The idea is that you can continue the next step (translate this into code) with the tools you choose. Even so, in a future article maybe I'll show you how to turn this logic into code with reactJS, as a reference.

Without further introductions, let's begin:

Requirements

The user can:

  • apply filters on a specific products collection (hotsale).
  • do infinite scrolling on products loading.
  • accumulate filters in the search.
  • maintain filters when reloading the page.
  • pass the URL to another person and this person will see same filters applied.

Problems

The main problem here was the first requirement, because the ERP the company uses has native filters, but they cannot be applied to a specific collection. So, this involved building the filters from scratch.

The solution was for the client to load the id of the collection in a placeholder and the Front End takes this datum to add it as a parameter in the product searches. This will allow the possibility of using the filters with other collections (when changing the id) or none (leaving the placeholder empty).

Another central issue was to consider that in the visible URL to the user, could arrive parameters external to this development (such as analytics tools or purchase conditions indicators) or parameters with incorrect ids or incorrect or contradicted values ​​(typos).

Therefore, the last three requirements involve special attention when reading the URL.

Data structure

First of all, we must decide how to save the data of our filters. Suppose we have a variable called bodyFilters. It can be an array of objects, where each one represents a specific criterion of the filter, which in turn contains several options. For example, a filter criterion can be by brand:

var bodyFilters = [
    {
        criterionId: 'brands',
        criterionName: 'BRANDS:',
        criterionOptions: [
            {
                id: 'brands-samsung',
                name: 'Samsung',
                param: 'fq=B:126'
            }, {...}, {...}, {...}
        ]        
    }, {...}, {...}, {...}
];

It is important that bodyFilters is an array so you can loop over it and apply for each criterion the logic that builds its view. Same consideration for the criterionOptions. Note that each option is an object that have an id to identify it, a name that will appear in the view and the param that will be necessary to build the URL and do the request.

We will also need a variable activeFilters, whose structure will be the same asbodyFilters, because: 1) we will use its data to update activeFilters and 2) we will cross both arrays data in order to determine which options are selected (maybe in the view they have a different colour or font weight).

Behaviour (part 1)

Second, we determine the flux of the development when the page loads:

  1. get bodyFilters

Of course, when the page loads, the first thing we want to do is get the bodyFilters. In the best case we can use static data, but it is very likely that we have to make one or more request (for example, in my case, in order to obtain the values ​​of the brands, specifications and ids of each one, with which the search parameters are built) and parse its data.

Probably, the bodyFilters value will not vary frequently, so we can store it in the cache and update it when necessary.

  1. get activeFilters

Now we read the URL and, crossing the data of bodyFilters, we identify if there are valid params. With this result we map bodyFilters and getactiveFilters (remember to consider if there is a default `activeFilters').

  1. create or update URLs

Once we have got the activeFilters we can use the params from each selected option and:

  • create the URL to do the request.
  • update the URL web page we history.replaceState().

I suggest making these URLs as similar as possible. Then, once the URL to do the request is ready:

  1. fetchProducts

And then we use the response (maybe need to parse it) to show the products or the error if exists.

Behaviour (part 2)

Third, we consider the interactions:

  1. handleFilterClick(currentCriterion, selectedOption)

When the user clicks for selecting or removing a filter option, we call this function that updates activeFilters. Note that we need to pass currentCriterion and selectedOption as params in order to know which option to update. And, after activeFilters is updated, repeat steps 3 and 4.

  1. Infinite scrolling

The typical situation is that in the URL of the fetchProducts request, there is a field that indicates the page number. For example, pageNumber = 1. For the infinite scrolling we will need some more tools:

  • A variable that indicates the pageNumber, whose default value is 1.
  • A function that checks if we must fetch products of the next page. Call it checkNextPage. For example, in my filters, at the bottom of the list there is a button. I check if that button is in viewport. If it is vissible, add +1 to pageNumber.
  • Listen the scroll event with a debounce and pass the above function.
  • If the pageNumber updates, then update the URLs and repeat steps 3 and 4.
  • Remember to reset pageNumber to 1 when handleFilterClick, that is step5.

Finally, what happens when there are no more products? How to avoid checkNextPage function adds +1 to pageNumber over and over again?

  • We need to create a boolean isNextPage. It is true by default and everytime we reset the search (handleFilterClick). But, if the fetchProducts returns success and empty products, we set isNextPage to false.
  • Remember, of course, to use this boolean inside checkNextPage. The idea is something like this:
    if (isNextPage && isBottomOfList) setNextPagePlusOne()
  • Next, as I said earlier, if the pageNumber updates, then update the URLs and repeat steps 3 and 4.

Conclusion

With this approach, we first define a data structure for the bodyFilters and activeFilters that consists of an array of objects, each representing a criterion and containing an array of options.

Second, we summarize the basic operation of a filter with infinite scroll in six steps: the first four related to the operation when loading the web page, and the other two related to user interactions.

It is not quantum physics. However, it is important to take a moment and consider a global view of the structure and logic of the FILTER before starting to program. This will simplify your code and prevent you from entering labyrinths or dead ends.

Be free to use this approach, improve it and build something great with it!

Discover and read more posts from Nico Diz
get started