For people familar with AngularJS, it's almost frighteningly easy to make a live-search on a repeating iterator.
Here's such an example: http://jsfiddle.net/r26xm/1/
Out of the box it just works. If nothing is typed into the search field it returns everything.
A big problem with this is that the pattern matching isn't very good. For example, if you search for ter
you get Teresa
and Peter
.
More realistically you want it to only match with a leading word delimiter. In other words, if you type ter
you want it only to match Teresa
but not Peter
because Peter
doesn't start with ter
.
So, to remedy that we construct a regular expression on the fly with a leading word delimiter. I.e. \bter
.
Here's an example of that: http://jsfiddle.net/f4Zkm/2/
Now, there's a problem. For every item in the list the regular expression needs to be created and compiled which, when the list is very long, can become incredibly slow.
To remedy that we use $scope.$watch
to create a local regular expression which only happens once per update to $scope.search
.
Here's an example of that: http://jsfiddle.net/f4Zkm/4/
That, I think, is a really good pattern. Unfortunately we've left the simplicity but we now have something snappier.
Unfortunately the example is a little bit contrived because the list of names it filters on is so small but the list could be huge. It could also be that we want to make a more advanced regular expression. For example, you might want to allow multiple words to match so as ter ma
should match Teresa Mayers
, John Mayor
and Maria Connor
. Then you could make a regular expression with something like \b(ter|ma)
.
For seasoned Angularnauts this is trivial stuff but it really helped me make an app much faster and smoother. I hope it helps someones else doing something similar.
Comments
Post your own commentObviously there is some discrepancy in what people think find-when-typing dialogs should do. ;D
I for instance find it very good that 'ter' gives you 'Teresa' AND 'Peter'! I'd rather state it explicitly when I want the start or end of a term by 'ter*' or '*ter'. But I'd say hits at the beginning should be sorted upfront.
On the other hand I think broaden the search with an extra word is the opposite of what I'd expect!: Just like the Firefox Awesome bar each word sorts again in the former hits to shorten the list further.
Right you are. I hope the point of the tip still comes through; that you can make a local regex with $scope.$watch
Oh yes of course! The simplicity of the whole thing is very enlightening! Thx for sharing!
Perhaps the ideal thing is to do two rounds of searching. If nothing is found when searching for "cus" then desperately return all things that have it anywhere in the string like "Circus".
Also, my thinking with the preference for `\d(...)` as in this blog is that for a live-search you kind of expect it to work similar to a autocomplete functionality.
I can't take any coding advice seriously from a person with a site that sucks so bad on mobile.
Sorry. I upgraded to the latest bootstrap. It should be a bit better now.
Really annoying comment there joebob - Not everyone is a front end responsive mobile first UX developer. Some people focus on other things.
Hi can anyone please get me the solution with coding example for the below problem.
For example, you might want to allow multiple words to match so as ter ma should match Teresa Mayers, John Mayor and Maria Connor.
a solution is given above like make a regular expression with something like \b(ter|ma). but can you give an example with complete code
To construct "\b(ter|ma)" from search string "ter ma" do the following:
var search = 'ter ma';
'\\b(' + search.trim().split(/\s+/).join('|') + ')'
Working example is here: https://jsfiddle.net/emilonlinester/f6rs7nx4/
What I would really like to do is have this working with a controller and a shared service, so that I can have the search on one view and the results on another.... can't seem to get the results page to bind or recognize angular directives....
THIS WAS SO USEFUL, I CAN'T EVEN. THANK YOU.
If I want for example want to search for both Cat and Child like for e.g.
Data:
IT>Software,Hardware
Kitchen > Knife. Fork
and if you search 'knife' for example, you will get:
<ul>
<li><b>Kitchen</b></li>
<li>Knife</li>
</ul>
$scope.cat = [
{
name: "IT",
tags: [ [
"Software",
"Hardware",
]
},
{
name: "Kitchen",
tags: [
"Knife",
"Fork",
]
}
];
Anyone know have a idea?