angularjs unnest ng-repeats into one query - angularjs

<div ng-repeat="blub in filtered = (blubs | filter:tag)">
<span ng-repeat="tag in blub.tags" class="tag-box">{{tag}}</span>
</div>
How can I unnest it into one query. I imagined it like this:
<span ng-repeat="tag in blub.tags in filtered = (blubs | filter: tag)>{{tag}}</span>
Object blub has more than one tag, there are more than one blub objects.
EDIT:
Plunker:
http://plnkr.co/edit/mWjyryOsV5zZJisZzV3D
GOAL: Reduce 2 times ng-repeat into one ng-repeat which shows the same tags.

In that situation I would recommend you first to create one collection instead of doing double looping.
<span ng-repeat="tag in getBlupList(filtered)" class="tag-box">{{tag}}</span>
Where getBlupList(filtered) are JS method. Some kind of reducer that creates one list instead of what you have.
I dont know how your collection look like but personally for me for such situation the best solution is to use Underscore.js lib. ".flatten()" or ".pluck()"

Related

Pre-count filtered results in an ng-repeat

I have a long list of products that are displayed using ng-repeat and I'm creating a filter on the left to pare down the list in the main content well.
I have a requirement to pre-count the results of each possible filter such that the text of the link of that filter button will show the results you will receive if you turn that filter on, just like happens in an e-commerce site.
I'm wondering how to do this with AngularJS. I'm hoping there's an easier way to do this other than creating a custom filter on the scope for each possible filter.
Note that I don't have to worry about chaining filter values- just the results of selecting that one filter.
Thanks, Scott
Not knowing exactly what the data model looks like I can't say if you need a custom filter. But for a simple data model you should be able to use a simple filter like so:
<ul>
<li ng-repeat="item in items">
<a ng-click="filter(item.type)">{{item.name}} {{(allData | filter:item.type).length}}</a>
</li>
</ul>
Here is a working example http://codepen.io/mkl/pen/GqpqYN

Abstract inline Angularjs filter

New to angular!
I've set up a very basic filter of which I'm quite happy with. Yet I want to transpose the inline filter to a .filter() function - I hope to use it like filter: dataFilter, or something similar.
So, currently I have some select fields:
<select ng-model="search.foo"><!-- options --></select>
<select ng-model="search.bar"><!-- options --></select>
And an ng-repeat of the sorted data:
<div ng-repeat="data in response.data | filter:{foo: search.foo, bar: search.bar}">
<!-- display sorted data -->
</div>
Above in the ng-repeat is what I would call the inline filter of which I want to abstract.
How do I go about doing this?
All guidance appreciated.
My end game aim is to show a message when there an no results in the filter. I believe the filter needs to be "abstracted" in order for this to work? Something along the lines of:
<p ng-show="(response.data | filter:blahFilter).length == 0">No results found.</p>
I would really advice you to move this to the controller. Then inside there just use your filter as a function call
$scope.myData = $filter('blaFilter')(response.data)
then
<p ng-show="myData.length == 0">No results found.</p>

quick-ng-repeat does not update view

I use quick-ng-repeat Quick-ng-repeat for my list to iterate because it is a huge list and I would improve performance.
Now I recognized that if I change the model, the view is not updated with this code:
<span quick-ng-repeat="item in collection track by $index" quick-repeat-list="items">
{{ item }}
</span>
With this code
<span ng-repeat="item in collection track by $index">
{{ item }}
</span>
every works fine.
Does anyone have any idee why this happens?
Thanks a lot!
quick-ng-repeat does not implement deep watch just like ng-repeat, it implement one way binding approach. So if your model changes frequently, don't use it.
In Angular 1.2 a new addition was made to the syntax of ngRepeat: the amazingly awesome track by clause. It allows you to specify your own key for ngRepeat to identify objects by, instead of just generating unique IDs.
This means that you can change the above to be ng-repeat="task in tasks track by task.id" and since the ID would be the same in both your original tasks and the updated ones from the server – ngRepeat will know not to recreate the DOM elements and reuse them
The Quick ng-repeat is doing one way binding ,it something similar to what we do in angularjs
<div ng-repeat="item in ::items">{{item.name}}</div>
This does not create unnecessary watches.
I think Quick-ng-repeat use Single binding same as in angular 1.4 like (::).Single binding mean it will be create a watcher for your repeat that why it will not effect when object is change.
<div ng-repeat="obj in ::objList">{{obj.name}}</div>

angularjs - track by in a for loop

I have a problem with the refresh button in my Angular application:
I have a json object with two arrays in it -> data = {array1: [], array2: []}
I want to loop both arrays and print the related values. To achieve that, I use the Angular ng-repeat directive like this:
ng-repeat="index in [] | index:getTotalNumberOfObjectsInArray1()"
...
<span ng-bind="data.array1[index]"></span>
<span ng-bind="data.array2[index]"></span>`
My Problem is, that on every click on the refresh-button these data will be recreated on the dom.
I learned the documentation about "track by" but i understand it only on objects (for example: ng-repeat="a in objects track by a.id")
How can I use this track by filter for my ng-repeat above, to prevent the recreation of my data?
You can use $index that is defined in a ng-repeat (cf.doc) but you have to have the two array with the same length.
Another solution could be to merge your arrays together and loop on it but I am not sure if it answer to your question.

Using same ng-repeat on one page - best practice?

In need the data from a ng-repeat on two places within the view. The code below works, but I am not sure if this is the way to do it. (I am new to Angular).
If a user clicks on a outlet-option the outlet-products get displayed. First I loaded the products below the outlet-option and used jQuery to move to the productsWrapper if a user clicks on an option. But then I needed to compile it again which made it a bit messy in my opinion.
There can be only one "#productsWrapper" and one ".outlet", so I came up with using the ng-repeat twice. But is this the way to go?
<div id="productsWrapper">
<div ng-repeat="element in elements track by $index" class="products" style="display: none;" id="prod-{{element.wonelement_id}}">
<outlet-product ng-repeat = "option in element.options"
class = "product"
option-data = "option"
element-data= "element"
chosen-data = "chosen">
</outlet-product>
</div>
</div>
<div class="outlet">
<div ng-repeat="element in elements track by $index">
<outlet-option
element-data = "element"
option-data = "element.option"
chosen-data = "chosen"
app-settings = "app">
</outlet-option>
</div>
</div>
I think what you proposed looks fine in a typical AngularJS way.
If you were applying filters to the ng-repeat clause, then I would have suggested applying that filter ahead of time in the controller so that it would only be run the one time. But since you are using no filters at all on the data, I think it is fine as you have it.

Resources