Search repeater with dynamic filter


#1

Hi all, I’m looking for some help with building a filterable search (see my projects attached). I’d like to be able to enter a keyword (e.g. Parker) and the search to return matching records. This bit I’ve done.

I’d then like to be able to select a filter from a list/dropdown (e.g. Clients) so that when I type a keyword it only returns records in that subset. This is the bit I’m struggling with.

Please can anyone help?

Search Filter.rp (86.1 KB)


#2

Hi!

The term for multiple filters winnowing down a list is “facet filters.” The first facet is the search text, and the second is the value of the dropdown.

We’ll use technique for solving this problem here. NOTE! Please go through this sample before reading the rest of the explanation, because otherwise it won’t make sense.

Note that in my modification of your file, I am setting Items Per Page of the repeater to Unlimited to force re-evaluation of the filters defined in onPageLoad, rather than a do-nothing filter. (It might be my imagination, but seems like it performs better.) Also, note that we never need to hide or show the repeater itself, as the filter automatically returns no rows when none of the rules apply.

Let’s look at the two facet filters defined in OnPageLoad one by one, because your situation is obviously different than the one set up in the facet filters post:

[[ ( sVal != "" && Item.Col1.toLowerCase().indexOf(sVal.toLowerCase() ) >= 0) || ( sVal != "" && Item.Col2.toLowerCase().indexOf(sVal.toLowerCase() ) >= 0) || ( sVal != "" && Item.Col3.toLowerCase().indexOf(sVal.toLowerCase() ) >= 0)]]    

That’s a long expression, but we really only need to discuss the first third. But first I’ll point out that && is a logical AND, || is a logical OR, != means not equals, and == means equals.

( sVal != "" && Item.Col1.toLowerCase().indexOf(sVal.toLowerCase() ) >= 0)

You are familiar with the part of the expression after the AND. Unfortunately, if the first parameter of .indexOf( ) is an empty string – e.g., if the search field is empty – the function always returns TRUE. So we have to AND that expression with a second expression, sVal != “”, to rule that out.

In English, the expression above says, "If the search text is not an empty string and Col1 contains the search text for a given row, return TRUE.

The next two expressions in the long expression are just like this one except targeting a different column, and the thee are OR-ed together, so that if any one of these things is TRUE for a given row, the whole expression will evaluate to TRUE.

The second facet filter further reduces the results of the first:

[[ sfVal == "All Records" || sfVal == Item.Col3 ]]

There are two conditions here OR-ed together:

sfVal == "All Records"

This basically returns all of the resultant rows of the first filter if the value of the result filter is All Records. Remember from the facet filters post, a filter doesn’t need to reference a column value at all; it merely needs to return TRUE or FALSE. This expression snippet will return true (thus the entire expression will return true) if the filter value is All Records.

The other possibility that we want to cover is if the filter value matches Col3 for the given row. (Note that I made the values in the filter dropdown exactly match the values in Col3. If you don’t want that to be the case, let me know and I can help you work around it.)

sfVal == Item.Col3

This returns true if the value in Col3 matches the filter.

So in English, the whole second filter means, "If the search filter is “All Records” or the search filter matches the value for Col3 for a given row, return TRUE.

I updated your file.

Live sample

file: Search Filter.rp (92.1 KB)

[Edit] I made the assumption that if the user selects a filter aside from All Records WITHOUT entering any text in the search field, no rows will be returned. Which makes sense logically, since when the filter says All Records, no rows are returned. But the user may be confused if, say, they don’t enter any search criterion and choose Employee from the filter, and nothing happens.

Would you want to show all employee rows in this scenario? If so, let me know. I’m sure we can adjust the filters to accommodate this scenario, but it would be a bit more complex. However, since this state is ambiguous, expectations could go either way. it might be best to disable the filter if no text is in the search field.


#3

Hi josephxbrick, that’s great! Thanks for your comprehensive response. I’ll make sure I read your explanation in detail and try to understand how you’ve achieved this.

In terms of your [Edit] at the bottom of your post, I’d like users to be able to select a filter before or after entering any text into the search field. So, they could pick a filter first, then enter the search term or enter a search term and then narrow down the results by picking a filter after. Your edited project seems to behave like this already.

Also, how would I display a row saying “No results found” if there are no matches?

Oh, one more thing, I’ve noticed that when there’s no search text entered, the repeater border (I think?) is being displayed in the top left-hand corner, under the search input. Can this be hidden?

Thanks again for your help with this!


#4

Hi!

So, should rows be displayed when the filter says All Records? It might feel strange for them not to be when selecting a different filter displays rows. But maybe that could be mitigated by changing the name of the All Filters label (at which point, you would need to update the name in the filters as well).

At any rate, I modified the filter so that if the field is blank and the filter is not All Records, it will show all rows that the filter applies to. However, if the field is blank and the filter IS All Records, then no rows are shown. You can play with it to see if this is the behavior that you want.

There is a bug when a border is applied to a repeater. Its size when no rows are displayed is 2 by 10 (at least in this case), whereas when there is no border it is properly 0 by 0. Here is a solution to that.

Enclose the repeater in a fit-to-content dynamic panel, and add this code to that panel.

OnResize
    if (value) [[This.width]] is less than 10
        hide repeater

Then add this line to the OnItemLoad handler of the repeater:

show repeater

Note that when a repeater returns no rows, OnItemLoad does not run even once. That update is in the file as well. Be careful to keep this repeater as fit-to-content. Note that if you manually resize the repeater, that setting is automatically turned off.

Here is the updated file. Search Filter 2.rp (99.4 KB)

[edit] I forgot your question about displaying “No rows” when there are none. You can add a “show message” command to the OnResize handler that hides the repeater, adding an ELSE IF to hide the message.


#5

I want to have my search box search the entire contents of my jobs table repeater. However, I am positive I am doing it wrong because I have set up my search box as a separate repeater - from a different tutorial - and I cannot figure out how to ‘set text’ for my search box so that it will search all the columns on my large repeater. Can anyone help? I’m struggling.

Thanks!

Job_Management_12_21.rp (648.7 KB)