AngularJS ng-repeat with limitTo - angularjs

Is there a way to type:
<div ng-repeat="item in items | limitTo:what">
where I can substitute "what" with something that will make it iterate through the whole list of items. (note items.length is not what I am searching for.. or it must be with some ugly if inside the html).

In the source for limitTo there is support for an infinite number (Infinity):
if (Math.abs(Number(limit)) === Infinity) {
limit = Number(limit);
} else {
limit = int(limit);
}
Looks like you should be able to set to Number.POSITIVE_INFINITY.
However, the resulting code would probably be no better than using items.length. And would certainly be less understandable.

you don't need {{ }}, here is the documentation
<div ng-repeat="item in items | limitTo:what">
in the controller
$scope.what = 3; // iterate only 3

This is simple man
<div ng-repeat ="item in items | limitTo:10">
or $scope.what = '10'; and use what in limit.

Related

Angular ng repeat filter inside ng repeat

I've been trying to make a list of geozones, with a select of taxes each (not all taxes apply to all geozones).
So I did a ng-repeat for the geozones, and inside each of them a ng-repeat with all taxes. Problem is I don't know how to send the id of the geozone being filtered at the moment. This is the code right now:
<md-option ng-repeat="tax in taxClasses | filter: filterTax" value="{{ '{{ tax.id }}' }}">{{ '{{ tax.name }}' }}</md-option>
and the JS:
$scope.filterTax = function(tax, n){
angular.forEach(tax.geoZone , function(geo){
if(geo === $scope.prices[n].geozoneId){
return true;
}
});
return false;
};
Need n to be the index of the geozone, or something of the sort. Thanks in advance!
Your idea is not that far off, but using filter: is not even necessary, as the pipe | is already a filter command:
ng-repeat="<var> in <array> | <filterFunction>:<...arguments>"
Thus you can create a filter (see https://docs.angularjs.org/guide/filter for details on that)
ng-repeat="tax in taxClasses | filterTax: <geozoneIndex>"
The value form the collection will be passed as the first argument of your filterTax function. Any further argument is passed separated by a colon :.
When you use this, you have to propagate a filter method like this:
app.module(...).filter('filterTax', function(/* injected services */) {
return function (/* arguments */ input, geozoneIndex) {
// function body
}
});
Alternatively use a filter function from your scope:
// template
ng-repeat="tax in filterTaxes(taxClasses, <geozoneIndex>)"
// script
$scope.filterTaxes = function(taxClasses, geozoneIndex) {
// do the whole filtering, but return an array of matches
return taxClasses.filter(function(taxClass) {
return /* in or out code */;
});
};
This means your geozoneIndex may be either a fixed value or being pulled from a variable, that's available in that scope.
Just be aware that your filterTax function will be called a lot, so if your page is getting slow you might want to consider optimizing that filtering.

How to filter an array by finding elemets in array in angularJs?

I'm new to angularJs. I'm facing an issue where i need to filter an array (in ng-repeat) by finding the element in array.
<div class="row" ng-repeat="(class_list_key, class_list) in trialList | filter: {class_id:selected_class_option_arr}">
I tried the above code (which is wrong). Here selected_class_option_arr is an array having values by which i need to filter trialList array using class_id.
Array selected_class_option_arr is like this -
["Sat_09:00_AM_10:30_AM", "Fri_10:00_AM_11:00_AM"]
I tried to find but didn't got proper example as per my requirement.
Provide a filter function in the ng-repeat and loop through the against array to filter out the required values:
<div class="row" ng-repeat="classList in trialList | filter: filterClass >
In the controller:
$scope.filterClass = function(classList) {
for(var i=0; i < selected_class_option_arr.length; i++) {
return classList.class_id.indexOf(selected_class_option_arr[i]) != -1
}
};
Working Plunker: https://plnkr.co/edit/yQ7D9fwwitfMktOkGjF8?p=preview

Angular-filter omit with dynamic element from scope

JS:
var MyApp = angular.module('SOFdemo',['angular.filter']);
MyApp.controller('SOFCtrl',['$scope','$resource','$location',function($scope,$resource,$location){
$scope.serverSizeOptions = [
{"name":"20 Users","value":20},
{"name":"30 Users","value":30},
{"name":"40 Users","value":40},
{"name":"50 Users","value":50},
{"name":"60 Users","value":60},
{"name":"70 Users","value":70},
{"name":"80 Users","value":80},
{"name":"90 Users","value":90}];
}]);
I want to display on a table the possible options for a customer that subscribe to a max and min size. I'm using the directive angular-filter
I assigned the controller to my body.
The following ng-repeat directive usage on my partial HTML working well for a tr:
< tr ng-repeat="(key,value) in (serverSizeOptions | omit: value<20 | omit: value>50)">
< td>{{key}}
< td>{{value}}
< /tr>
Now, I would like to change 20 or 50 by my project size like:
< tr ng-repeat="(key,value) in (serverSizeOptions | omit: value<20 | omit: value> project.size.value)"> ...
But here, filter is not applied and I have all my list.
project.size.value is on my current scope.
I tried several configuration since hours and I'm starting to think that it's not possible to do what I'm expecting.
Any help will be appreciate.
You can use the filterFilter and define a function on your scope, that selects the valid values.
ng-repeat = "item in serverSizeOptions | filter:myFunction"
$scope.myFunction = function(item) { ..your logic here return a boolean }

Angularjs get length of returned filter in ng-repeat

I'm using ng-repeat to create a list of entires and using a filter.
Is it possible to get the number of entries returned, like a length
data-ng-repeat="entry in entries | filter: { country_code : countryCode }"
It is little bit tricky, use ng-init:
ng-init="filter_len = (entries | filter: { country_code : countryCode }).length"
Example: http://jsfiddle.net/KJ3Nx/
As you know filter responsible to "filter" the input list and it returns filtered list where objects have the same structure. Otherwise you get digest cycle reentering that causes Exceptions (aka > 10 cycles).
1st way
Get length after filtering:
<pre>{{(entries| myfilter:types).length }}</pre>
See Example
2nd way
Use custom filter and get length from there.
iApp.filter('myfilter', function() {
return function( entries) {
var filtered = [];
angular.forEach(entries, function(entry) {
filtered.push(entry);
});
// here fetch list length
return filtered;
};
});
I suppose the following code will work for you:
<p>Filtered number: {{(entries|filter:{country_code:countryCode}).length}}</p>
<p>Total number: {{entries.length}}</p>

Ng-Repeat array to rows and columns

Thanks for taking the time to read this, I was wondering how I might be able to use ng-repeat to create a grid like box of options. I would like to take an array repeat nth number of items and then move to the next row or column until all items are listed. e.g.
assuming I had an array like [opt1,opt2,opt3,opt4,opt5,opt6,opt7] I would like to display it like this:
opt1 opt2 opt3
opt4 opt5 opt6
opt7
This is more a styling/markup problem than an AngularJS one. If you really want to, you can do:
<span ng:repeat="(index, value) in array">
{{value}}<br ng:show="(index+1)%3==0" />
</span>
http://jsfiddle.net/JG3A5/
Sorry for my HAML and Bootstrap3:
.row
.col-lg-4
%div{'ng:repeat' => "item in array.slice(0, array.length / 3)"}
{{item}}
.col-lg-4
%div{'ng:repeat' => "item in array.slice(array.length / 3, array.length * 2/3)"}
{{item}}
.col-lg-4
%div{'ng:repeat' => "item in array.slice(array.length * 2/3, array.length)"}
{{item}}
There is another version, with possibility to use filters:
<div class="row">
<div class="col-md-4" ng-repeat="remainder in [0,1,2]">
<span ng-repeat="item in array" ng-if="$index % 3 == remainder">{{item}}</span>
</div>
</div>
If all of your items are in one single array, your best bet is to make a grid in CSS. This article should be helpful: http://css-tricks.com/dont-overthink-it-grids/
You can use $index from ng-repeat to apply the correct class for your column (in this case a 4 column grid):
<div class="col-{{ $index % 4 }}"></div>
If you have a 2 dimensional array (split into rows and columns) that opens up more possibilities like actually using an HTML table.
I find it easier to simply use ng-repeat combined with ng-if and offsetting any indexes using $index. Mind the jade below:
div(ng-repeat="product in products")
div.row(ng-if="$index % 2 === 0")
div.col(ng-init="p1 = products[$index]")
span p1.Title
div.col(ng-if="products.length > $index + 1", ng-init="p2 = products[$index + 1]")
span p2.Title
div.col(ng-if="products.length <= $index + 1")
Between Performance, Dynamics and Readability
It seems putting the logic in your JavaScript is the best method. I would just bite-the-bullet and look into:
function listToMatrix(list, n) {
var grid = [], i = 0, x = list.length, col, row = -1;
for (var i = 0; i < x; i++) {
col = i % n;
if (col === 0) {
grid[++row] = [];
}
grid[row][col] = list[i];
}
return grid;
}
var matrix = listToMatrix(lists, 3);
console.log('#RedPill', matrix);
# Params: (list, n)
Where list is any array and n is an arbitrary number of columns desired per row
# Return: A matroid
# Note: This function is designed to orient a matroid based upon an arbitrary number of columns with variance in its number of rows. In other words, x = desired-columns, y = n.
You can then create an angular filter to handle this:
Filter:
angular.module('lists', []).filter('matrical', function() {
return function(list, columns) {
return listToMatrix(list, columns);
};
});
Controller:
function listOfListsController($scope) {
$scope.lists = $http.get('/lists');
}
View:
<div class="row" ng-repeat="row in (lists | matrical:3)">
<div class="col col-33" ng-repeat="list in row">{{list.name}}</div>
</div>
With this, you can see you get n number of rows -- each containing "3" columns. When you change the number of desired columns, you'll notice the number of rows changes accordingly (assuming the list-length is always the same ;)).
Here's a fiddle.
Note, that you get the ol' Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!. This is because Angular is recalling the matrical function upon every iteration. Allegedly, you can use the as results alias to prevent Angular from reevaluating the collection, but I had no luck. For this, it may be better to filter the grid inside of your controller and use that value for your repeater: $filter('matrical')(items) -- but please post back if you come across an elegant way of filtering it in the ng-repeat.
I would stress, again, you're probably heading down a dark alley by trying to write the logic in your view -- but I encourage you to try it in your view if you haven't already.
Edit
The use of this algorithm should be combined with a Matrical Data-Structure to provide methods of push, pop, splice, and additional methods -- in tandem with appropriate logic to complement Bi-Directional Data-Binding if desired. In other words, data-binding will not work out of the box (of course) as when a new item is added to your list, a reevaluation of the entire list must take place to keep the matrix's structural integrity.
Suggestion: Use the $filter('matrical')($scope.list) syntax in combination with $scope.$watch and recompile/calculate item-positions for the matrix.
Cheers!

Resources