How to have or condition on a ng-repeat - angularjs

How to have or condition on this repeat ?
I want to filter this tbody depending of a value
MY TABLE
<tbody ng-repeat="Fund in ListTask | filter:{CreationDate: manager.start}:true | filter:{DueDate: manager.end}:true | filter:{Beneficiary: currentNode.name}:true | filter:{Title: currentNode.name}:true | filter:{category: currentNode.name}:true">
<tr ng-dblclick="open(Fund.id)" data-toggle="modal" data-target="{{Fund.type}}">
<td>{{Fund.id}}</td>
<td>{{Fund.Beneficiary}}</td>
<td>{{Fund.Title}}</td>
<td>{{Fund.status}}</td>
<td>{{Fund.category}}</td>
<td>{{FormField.shortDate(Fund.CreationDate)}}</td>
<td>{{FormField.shortDate(Fund.DueDate)}}</td>
<td>{{Fund.Team}}</td>
</tr>
</tbody>

It seems you have to implement your own filter.
Example :
.filter('specialFilter', function() {
return function(funds,manager,currentNode) {
var filtered = [];
angular.forEach(funds, function(fund) {
if (fund.CreationDate ==manager.start|| fund.category==currentNode.name)
filtered.push(fund);
});
return filtered;
};
})
<tbody ng-repeat="Fund in ListTask | specialFilter:manager:currentNode"
To notice, if you have an important number of funds (>2000), it could be better for performances to build yourself a specific array of data filtered.

Related

Filter on column and also sort in descending order in AngularJS

How can I sort in descending order but also filter on column in AngularJS? I have the following code that will default to the most recent timestamp.
<tr ng-repeat="item in log | orderBy:'-timestamp' ">
<td>{{item.timestamp | date: 'MM/dd/yyyy HH:MM'}}</td>
<td>{{item.Action | removeHTMLTags | strip }}</td>
<td>{{item.AO}}</td>
</tr>
I also have the following js code that will work for filtering on the column header.
$scope.reverseOrder = true;
$scope.sortField = '';
$scope.sortBy = function(sortField) {
$scope.reverseOrder = ($scope.sortField == sortField) ? !$scope.reverseOrder : false;
$scope.sortField = sortField;
}
<tr ng-repeat="item in log | orderBy:sortField:reverseOrder">
<td>{{item.timestamp | date: 'MM/dd/yyyy HH:MM'}}</td>
<td>{{item.Action | removeHTMLTags | strip }}</td>
<td>{{item.AO}}</td>
</tr>
I would like to both filter on the column but also default to show the most recent timestamps on top.
I tried the following but it did not work.
ng-repeat="item in log | orderBy:sortField:reverseOrder | orderBy: '-timestamp'"
In order to understand why your code isn't working you must understand first, how the orderBy filter works in angularjs. In your ng-repeat the orderBy filter has two parameters sortField and reverseOrder. For them to work you must have a controller that has two $scope variables named respectively sortField and reverseOrder. The first parameter is to determine which key should orderBy use to order your array and the second one is a boolean that specifies would the order be reversed or not.
In my attempt to reproduce your example, I took the liberty of using unix timestamps in my logs array. So in the controller,
$scope.searchText = "";
$scope.sortField = "timestamp";
$scope.reverseOrder = false;
$scope.logs = [
{
timestamp : 2147450400000,
Action : 'bal sal',
AO : 'abcd'
},
{
timestamp : 979840800000,
Action : 'bal sal2',
AO : 'abcd2'
},
{
timestamp : 1579370400000,
Action : 'bal sal2',
AO : 'abcd2'
}
]
$scope.sortBy = function(sortField) {
$scope.reverseOrder = ($scope.sortField === sortField) ? !$scope.reverseOrder : false;
$scope.sortField = sortField;
};
Also in the example you provided, they passed the column name via a function. So in your html you need to have something like this.
<input type="text" ng-model="searchText">
<table>
<thead>
<th ng-click="sortBy('timestamp')">Time Stamp</th>
<th ng-click="sortBy('Action')">Action</th>
<th ng-click="sortBy('AO')">AO</th>
</thead>
<tr ng-repeat="item in logs | orderBy:sortField:reverseOrder| filter:searchText">
<td>{{item.timestamp | date :'MM/dd/yyyy HH:MM'}}</td>
<td>{{item.Action}}</td>
<td>{{item.AO}}</td>
</tr>
</table>
Hope this clears your confusions.

foreach to foreach array in angularjs

I am trying to update specific data of an array that is being displayed thru ng-repeat.
Given the datas:
$scope.cartItems = [];
$scope.items = [{code: 'ABC', cash:'20.00', charge: '25.00'},
{code: 'DEF', cash:'10.00', charge: '15.00'},{code:
'GHI',cash:'30.00', charge: '35.00'}];
then i have this table
Item | Price | Action
ABC | 20.00 | Add
DEF | 10.00 | Add
ng-click="add(Item,Price)"
$scope.add = function(Item,Price){
var itemscart = {};
itemscart.code = Item;
itemscart.price = Price;
$scope.cartItems.push(itemscart)
}
and is being displayed like this thru html table.
ng-repeat="cart in cartItems"
Item | price | bracket
ABC | 20.00 | Cash //dropdown
DEF | 10.00 | Cash //dropdown
And i have this dropdown select tag with option value; "Cash" or "Charge"
If in the dropdown i selected charge. The expected output of the html table must be:
Item | price | braket
ABC | 25.00 | Charge //dropdown
DEF | 15.00 | Charge //dropdown
I have tried:
if($scope.optionval == 'Charge'){
var price = 0;
$scope.cartItems.forEach(function(v){
if(v.code == ($scope.items.forEach(function(c){c.code; price =
c.charge; })))
v.PRICE = price;
console.log(v.PRICE) //gets the last row
console.log(price) //null
});
}
As per your displayed and expected table, you can try something like:
On change of CASH to CHARGE, make a function call on ng-change in
which pass the selected object with selected 'braket'.
Then in function call you can filter data.
In my opinion you could use a different approach, like using ng-show or ng-if directives to get the results you are trying to achieve
Try adding a custom field in your $scope in order to store which price should be shown, then you have two choices: to modify every field or separately:
Display independiently:
app.js
$scope.items = [{code: 'ABC', cash:'20.00', charge: '25.00', displaying:'cash'},{...}
HTML
<tr>
<th>Item</th>
<th>Price</th>
<th></th>
</tr>
<tr ng-repeat="cart in whatever">
<td>{{cart.item}}</td>
<td ng-show="cart.displaying=='cash'>{{cart.cash}}</td>
<td ng-show="cart.displaying=='charge'>{{cart.charge}}</td>
<td>{{cart.displaying}}</td>
<td>*Dropdown to modify this specific 'displaying' field*</td>
</tr>
Every field at the same time:
app.js
$scope.displayingitems = 'cash'
HTML
*Dropdown to modify this specific 'displaying' field*
<tr>
<th>Item</th>
<th>Price</th>
<th></th>
</tr>
<tr ng-repeat="cart in whatever">
<td>{{cart.item}}</td>
<td ng-show="displayingitems=='cash'>{{cart.cash}}</td>
<td ng-show="displayingitems =='charge'>{{cart.charge}}</td>
<td>{{displayingitems}}</td>
<td></td>
</tr>

Filtering based on search with Pagination i.e. on entire set of records

I am able to search only the current page records, However I need to search the entire set of records returned from server. This is my code:
<tr ng-repeat="brt in $parent.visibleBrtList = (currBrtList
| orderBy: state.orderBy : state.reverseOrderByDirection
| filter: pageFilter(state.page, state.itemsPerPage)
| filter: searchKeyword) ">
I have also tried to modify it like this:
<tr ng-repeat="brt in currBrtList
| filter: pageFilter(state.page, state.itemsPerPage)
| filter: searchKeyword">
currBrtList has 200 records, itemsPerPage is 10.
Here is pageFilter function:
$scope.pageFilter = function() {
var from = $scope.state.page * $scope.state.itemsPerPage;
var to = from + $scope.state.itemsPerPage;
return function(item, index) {
return index >= from && index < to;
}
}
Use the limitTo filter for pagination:
<tr ng-repeat="brt in currBrtList
| orderBy: state.orderBy : state.reverseOrderByDirection
| filter: searchKeyword
̶|̶ ̶f̶i̶l̶t̶e̶r̶:̶ ̶p̶a̶g̶e̶F̶i̶l̶t̶e̶r̶(̶s̶t̶a̶t̶e̶.̶p̶a̶g̶e̶,̶ ̶s̶t̶a̶t̶e̶.̶i̶t̶e̶m̶s̶P̶e̶r̶P̶a̶g̶e̶)̶
| limitTo: state.itemsPerPage : state.page*state.itemsPerPage" >
The first argument is the limit; the second, the begin.
Also be sure to filter before pagination.
For more information, see
AngularJS limitTo Filter API Reference

Angular JS multiple filter query

I'm a newcomer to Angular/JS so please be kind ...
I'm having a problem (probably with myself trying to wrap my brain around Angular) with some code where I want to use two different filters (I think) on a dataset with ng-repeat. Firstly here is a screen shot of the html form items and data output I am working with;
Here is the basic (stripped down) HTML code for the setup above;
<div ng-controller="customersCrtl">
Records Per Page:
<select ng-model="entryLimit" class="form-control">
<option>50</option>
<option>100</option>
<option>250</option>
<option>500</option>
<option>1000</option>
</select>
Record Type:
<select ng-model="entryType" class="form-control">
<option>All</option>
<option>Baptism</option>
<option>Marriage</option>
<option>Burial</option>
</select>
Filter Text:
<input type="text" ng-model="search" ng-change="filter()" placeholder="Filter" class="form-control" />
Filtered {{ filtered.length }} of {{ totalItems }} Total Records
<div ng-show="filteredItems > 0">
<table>
<thead>
<th>Event Date <a ng-click="sort_by('eventDate');">sort</a></th>
<th>Event Type <a ng-click="sort_by('type');">sort</a></th>
<th>Indivdual(s) <a ng-click="sort_by('name');">sort</a></th>
<th>Location <a ng-click="sort_by('location');">sort</a></th>
<th></th>
</thead>
<tbody>
<tr ng-repeat="data in filtered = (list | filter:search | orderBy : predicate :reverse) | startFrom:(currentPage-1)*entryLimit | limitTo:entryLimit">
<td>{{data.eventDate | date:'mediumDate'}}</td>
<td>{{data.type}}</td>
<td>{{data.name}}</td>
<td>{{data.location}}</td>
<td>View Record</td>
</tr>
</tbody>
</table>
</div>
... and here is the associated Angular JS code I currently have;
var app = angular.module('myApp', ['ui.bootstrap']);
app.filter('startFrom', function() {
return function(input, start) {
if(input) {
start = +start; //parse to int
return input.slice(start);
}
return [];
}
});
app.controller('customersCrtl', function ($scope, $http, $timeout) {
$http.get('ajax/getMarkers.php').success(function(data){
$scope.list = data;
$scope.currentPage = 1; //current page
$scope.entryLimit = 50; //max no of items to display in a page
$scope.entryType = 'All'; //Record type to display in a page
$scope.filteredItems = $scope.list.length; //Initially for no filter
$scope.totalItems = $scope.list.length;
});
$scope.setPage = function(pageNo) {
$scope.currentPage = pageNo;
};
$scope.filter = function() {
$timeout(function() {
$scope.filteredItems = $scope.filtered.length;
}, 10);
};
$scope.sort_by = function(predicate) {
$scope.predicate = predicate;
$scope.reverse = !$scope.reverse;
};
});
getMarkers.php in the above Angular code snippet returns JSON results formatted like so;
{"id":"646","eventDate":"1576-05-13","name":"John Phillip","type":"Baptism","churchName":"St. Marys","locationid":"563","location":"Swainswick, Somerset, UK","lat":"51.414211","lng":"-2.351418"},
{"id":"647","eventDate":"1577-07-01","name":"Jane Volantyne","type":"Baptism","churchName":"St. Mary the Virgin","locationid":"564","location":"Horsham, Sussex, UK","lat":"51.059750","lng":"-0.330879"},
{"id":"132","eventDate":"1634-05-09","name":"Katherine Stanley","type":"Burial","churchName":"St. James","locationid":"567","location":"Titsey, Surrey, UK","lat":"51.276505","lng":"0.018909"}
... etc. etc.
This currently works in so-far-as if a user types something in the "Filter Text" box, the table updates to only show entries that match the user text.
This is fine, but what I also want to be able to do is use the drop down "Record Type" box (with the defined entries All, Baptism, Burial, Marriage) to only show/filter the records with that particular "Event Type" in the table.
Is this even possible? Can you apply two concurrent filters to an ng-repeat in Angular, because I've tried and failed several times and am on the verge of giving up!!!
Am I asking something stupidly difficult or stupidly easy?
Yes, its very possible to filter the table based on multiple conditions, You could add a filter function to the table as:
<tr ng-repeat="data in filtered = (list | filter:filterEvents | orderBy : predicate :reverse) | startFrom:(currentPage-1)*entryLimit | limitTo:entryLimit">
<td>{{data.eventDate | date:'mediumDate'}}</td>
<td>{{data.type}}</td>
<td>{{data.name}}</td>
<td>{{data.location}}</td>
<td>View Record</td>
</tr>
Basically, $scope.filterEvents is called every time the table is populated and you could filter out the required items using this in the controller:
$scope.filterEvents = function(item){
//Here item is the array element from the table
which is automatically passed in the filter function.
return item.type.toLowerCase().indexOf($scope.entryType.toLowerCase()) != -1 ||
item.name.toLowerCase().indexOf($scope.search.toLowerCase()) != -1
}
Where , $scope.entryType is the option selected in the dropdown and $scope.search is the keyword for searching.
Ps: You would need to remove the ng-change=filter() from search textbox and handle the return if $scope.entryType = "All"

Angular - Filter an array

I was wondering how I can filter an array to show only results if a property in the array is empty. I have tried the following but to no avail:
<tr ng-repeat="performanceOrder in performanceOrders | filter: salesId.length === 0">
I only want to show results if salesId is empty, is this possible?
Edit
salesId is a property of performanceOrder
performanceOrder: {
salesId: "S273626",
status: "Open",
...
}
With ngShow:
<tr ng-show="!salesId.length" ng-repeat="performanceOrder in performanceOrders">
With ngIf:
<tr ng-if="!salesId.length" ng-repeat="performanceOrder in performanceOrders">
You can use a function inside the filter like this:
<tr ng-repeat="performanceOrder in performanceOrders | filter: myFilter()>
Then, in your corresponding controller, you can do something like:
$scope.myFilter = function (val) {
return val.salesId.length === 0;
}

Resources