How to filter angular model (array) without destroying it

1110 picture 1110 · Feb 27, 2016 · Viewed 8.1k times · Source

I have a model for my view.
That model is array of objects:

var arr = { "12345qwery": { prop1: "value", prop2: "value" } } // contains 500 items

And today I am filtering it in the following way:

arr = $filter('filter')(arr, filterTerm); // contains 4 items

And after this line I get nice filtered data but if I run this filter again I don't have 500 items in it but 4.
So to avoid this I store original array in temporary object and when user change filter I first update arr with backup data (it's original 500 items) and do the filtering.
Now I get in trouble as I have multiple filters and I must restore original data before each filter... anyway it is a mess :)
Is there any better (angular) way to make this in javascript filtering?

UPDATE

To explan better what is issue I created plunker:

https://plnkr.co/edit/99b02UtUfPeM3wl4IiX6?p=preview

As you can see I load markers with objects and want to filter it via text field.
But I can't as I always get some errors.
Am I doing anything wrong here?
And to avoid this and implement filter somehow that is why I decided to do it in code and keep original array after each filter, but this is very complex solution and I wan't to make it in a more natural angular way.

BOUNTY UPDATE

I am filtering object in js code because I can't find a way to filter markers on this directive in a standard angular way.
That is why I filter in code and before filter always make a copy of it.
I need help to filter marker objects on this directive in a standard angular way.
Plunker implement this directive but I don't know how to filter it.

Answer

MrHaze picture MrHaze · Mar 4, 2016

Ok.. So you have a few things going on.

Issues

  • Scoping: Move your scope a bit out. Since you need to use filterTerm it needs to be within your controller scope, so move the scope a level out. I moved it out to the <body> tag - see plnkr.

  • Structure: Try to always include your JS files at the end of the <body> tag, and make sure you have the right order. I.e include angular.js before angular-simple-logger.js

  • Use of $scope: You can use scope directly, you don't need to extend it, that just makes it harder to read.

  • Model structure: Your Markers elements are a level too deep, I make the Markers variable an array of marker objects.

Solution

Use Angular's filter, it's pretty good, but need to be used properly. Generally it's like this: {{ array_to_filter | filter : filter_term}}

So in this case you can use it like so:

<leaflet defaults="defaults" markers="markers | filter: filterTerm " height="480px" width="640px"></leaflet>

Should be working now, just try to search for London or Park.

If you use a filter in your JS code it's easier to just make it a function where the variable dies at the end of it's scope. Otherwise you will always be overwriting your variable.

TL;RD

Here's a plnkr containing the working version.