How to sort table by value using ng-if? - angularjs

I'm a novice at AngularJS and trying to get my table to only show the rows that have a 'color' value of true when the user selects the 'Color Only' item from the Sort By drop down menu.
Here's my sort menu code:
<label>Sort By:</label>
<select ng-model="orderProp">
<option value="title">Title</option>
<option value="filename">File Name</option>
<option value="class">Classification</option>
<option value="color">Color Only</option>
</select>
Here is my table code:
<table>
<thead>
<tr>
<th>Classification</th>
<th>Title</th>
<th>File</th>
<th>Color</th>
</tr>
</thead>
<tbody>
<tr ng-animate="'animate'" ng-repeat="item in filtered = (pptData | filter: query | orderBy: orderProp)">
<td>{{item.class | uppercase}}</td>
<td>{{item.title}}</td>
<td>{{item.filename}}</td>
<td>{{item.color}}</td>
</tr>
</tbody>
</table>
I tried adding ng-if="color"to the ng-repeat directive but that did not work. Live link here.

Use
ng-if="orderProp !== 'color' || item.color"
on your ng-repeat element.
As you should know, when you refer to a property in an Angular directive expression, the property is resolved against the current $scope. ng-repeat creates a child scope for every iteration. When you specify ng-repeat="item in collection", you can then reference that child scope via the property item.
The color property is on that item child scope, not on the outer scope. Thus, saying ng-if="color" will result in none of the rows being rendered, because $scope.color is undefined. ng-if="item.color" will resolve against the item scope, and the row will only be rendered if item.color is defined.
However, if you only want to filter out those rows when the user has selected the color filtering option, you need to make sure you check the orderProp. Thus,
ng-if="orderProp !== 'color' || item.color"
gets the behavior you are looking for.
I suspect you will want to continue to do more complex filtering on these rows as you develop the code. In that case, I would recommend instead writing a function in your controller:
$scope.shouldShowRow = function(row, index) {
var show = $scope . orderProp !== 'color" || row.color;
// more logic for determining show/hide here
return show;
}
And then in your template:
<tr ng-repeat="item in (pptData | filter: query | orderBy: orderProp)"
ng-if="shouldShowRow(item, $index)">
<!-- your row markup here -->
</tr>
$index is a handy value that ng-repeat creates. You may not need it, but it might be useful.
As a suggestion, you should look into the controllerAs syntax. It requires you to name all of your controllers' scopes, and will help you keep track of what scope you are using when:
<div ng-controller="MyController as my">
...
<tr ng-repeat="item in (my.pptData | filter: query | orderBy: my.orderProp)"
ng-if="my.shouldShowRow(item, $index)">
...
</tr>
</div>
ControllerAs:
http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/

Related

How can i conditionally display an element using AngularJS

I want to display an element conditionally based on the value of another parameter PaymentTypeid. After setting the condition as below the element Payment Channel is not rendering in the UI:
<tr ng-init="paymentMode='BANK CABS'" ng-if="json.name == 'paymentTypeId' && json.property == '1'">
<td><strong>{{ 'label.heading.paymentchannel' | translate }}:</strong></td>
<td ><span >{{paymentMode}} </span></td>
</tr>
However when i refactor the markup as below the element is showing as :
<tr ng-init="paymentMode='BANK CABS'">
<td><strong>{{ 'label.heading.paymentchannel' | translate }}:</strong></td>
<td ><span >{{paymentMode}} </span></td>
</tr>
PaymentTypeId is in a json array defined as follows in the controller:
scope.details = {};
resourceFactory.auditResource.get({templateResource: routeParams.id}, function (data) {
scope.details = data;
scope.details.paymentMode="";
scope.commandAsJson = data.commandAsJson;
var obj = JSON.parse(scope.commandAsJson);
scope.jsondata = [];
_.each(obj, function (value, key) {
scope.jsondata.push({name: key, property: value});
});
});
In the view PaymentTypeid renders as :
<table class="table" data-ng-show="details.commandAsJson" data-anchor>
<tbody>
<tr data-ng-repeat="json in jsondata">
<td class="width20"><strong> {{json.name}}</strong></td>
<td class="width80">{{json.property}}</td>
</tr>
</tbody>
</table>
Any insight on what i might be getting wrong. Im not entirely sure between using ng-if/ng-show or whether im setting json.property correctly.
Assuming that you have knowledge of scope in AngularJS.
There is a difference between using ng-if and ng-show. Whenever you use ng-if , it creates it own child scope. and you can manage it in custom directive that deals with its child scope (child scope is not available in controller unless you write your code in a way, that will make it available in controller) and you can hack the scope to use it in controller too. But that is not the case in ng-show.
When you use ng-show it will not remove your HTML from the DOM tree but if you use ng-if it will also remove your html from DOM tree. (To assist your confusion which one to use)
You have a scope issue here , if i'm getting it right. Use ng-show and it will work.
<div ng-show="condition">
your html markup
</div>

ng-repeat or ng-options How can I automatically select the last row in a table ?

How I can I automatically select the last row in a table
ng-repeat="unit in selectedOrder.products" using something like select by track by $index == desc or alternatively ng-options
<div class="search" ng-show="selectedOrder">
<table class="table table-bordered">
<tr><th>Item</th><th>Name</th><th>ValueToday</th></tr>
<tr ng-repeat="unit in selectedOrder.products">
<td><img ng- src="http:images/thumbnails/{{unit.shortname}}_tn.jpg" width=40 height=40
alt="{{ unit.shortname | limitTo: 18}} Photo"></td>
<td>{{unit.name | limitTo:18 }}</td>
<td>{{unit.valuetoday| currency:"£"}} </td>
</tr>
</table>
<div class="search" ng-show="selectedOrder">
<table class="table table-bordered">
<tr><th>Item</th><th>Name</th><th>ValueToday</th></tr>
<tr ng-repeat="unit in selectedOrder.products" ng-if="$last">
<td><img ng- src="http:images/thumbnails/{{unit.shortname}}_tn.jpg" width=40 height=40
alt="{{ unit.shortname | limitTo: 18}} Photo"></td>
<td>{{unit.name | limitTo:18 }}</td>
<td>{{unit.valuetoday| currency:"£"}} </td>
</tr>
</table>
will give you only the last row selected
In ng-repeat you can use the $last special variable to apply something only if it's the last element. see: https://docs.angularjs.org/api/ng/directive/ngRepeat
you can use it as a condition for anything you want to do in the tag. like
<img class="{{$last ? 'selected'}}" ng-class="{'selected': $last}" ng-if="$last" ....>
or however you like (these are just examples)
Always keep in mind though that using angular means that you have to edit your model to apply changes to your view, so if you want to have an element selected you have to do something to your model so that the element contains a value that makes it selected and then your view should reflect this.
For example in your controller you can check which element is the last in your ng-repeat array and add a selected variable, then in your view do something to make it look like your element is selected (for example: ng-class="{'selected': element.selected}") otherwise, by working on the view only you can make it look like the element is selected using $last but it won't be really selected in your model
In fact In ng-options (so we are talking about a select) you have to change your model in order to reflect your choice. So for example if your select has an attribute like this: ng-model="selected" then in your controller you set the $scope.selected variable to the last element of the array containing the values for your ng-options
You could use something like ng-if="$index == $last"

how to display the number of filtered rows outside table definition?

I have implemented a filter for my ngtable. Trying to display the number of filtered items like this:
How to display nr of filtered rows here? Outside the table definition?
{{filtered.length}} result(s) matching the filter
<table ng-table="tableParams" class="table">
<tr ng-repeat="account in filtered =($data | filter:search.accountName | filter:search.id)">
<td>{{filtered.length}}</td>
<td data-title="'id'">
{{account.account.accountId.id}}
</td>
<td data-title="'name'">
{{account.account.accountName}}
</td>
</tr>
</table>
plunkr: http://plnkr.co/edit/Sx4YAO?p=preview
Just add $parent before your filtered in your ng-repeat and you should be fine.
Ng-repeat has an isolated scope.
<tr ng-repeat="account in $parent.filtered =($data | filter:search.accountName | filter:search.id)">
If you create the array before you use it within the child scopes then they'll reference and use the one from the parent scope
JS
$scope.model = {filtered:[]}
HTML
How to display nr of filtered? {{model.filtered.length}} result(s) matching the filter
<tr ng-repeat="account in model.filtered =($data | filter:search.accountName | filter:search.id)">
http://plnkr.co/edit/mcuN34?p=preview
Use built in function:
total() {{ tableParams.total() }}

Add fiter dynamically to ng-repeat

I want add the filters to the ng-repeat depending on there checkbox state.
<li ng-repeat="user in users | filter: filters">
{{user.name}} {{user.job}} {{user.min}}-{{user.max}}
</li>
Can filters be an array?
The second Questions is, how can i show all records, when $scope.min and $scope.max are empty (at init)?
http://jsfiddle.net/nofear87/H5GMD/3/
Yes, you can change filters dynamically quite easily, just assign a scope variable and you can modify it.
Example here: http://plnkr.co/edit/Au8KFg?p=preview
If you have
<li ng-repeat="user in users | filter: filters">
then your $scope variable is
$scope.filters = {minMax: false, ... };
As for the checkboxes, if your
<input ng-model="minMaxFilter" type="checkbox" ng-change="filters['minMax] =! filters[minMax]"/>MinMAX
if you want to just change the state of a filter
or if you want to add a new filter, you can attach a function with ng-click or just push a new value
<input ng-model="newFilterToAdd" type='text' > <button ng-click="filters.push(newFilterToAdd);">Add Filter</button>
to show all records, you need to not apply the filter (such as making it empty) or assigning a null to it
You can try adding two filters for your requirement.
<li ng-repeat="user in users | filter: searchText | minMax : filterParams">
{{user.name}} {{user.job}} {{user.min}}-{{user.max}}
</li>
Here is working Fiddle.
Hope it will help you.

Angular js: Access data filtered in ng-repeat (ngRepeat) from controller

I need to access data that was already filtered on a template (inside a ng-repeat) from my controller.
Here's what I mean:
I have this table in my template:
<table class="table">
<thead>
<th>Name</th>
<th>Gender</th>
</thead>
<tbody>
<tr ng-repeat="person in persons | filter:query">
<td>{{person.name}}</td>
<td>{{person.gender}}</td>
</tr>
</tbody>
</table>
Then I have a <select> that is used to filter data by gender
<h1>Cluster:</h1>
<select ng-model="query.gender" >
<option value ="">ALL</option>
<option value ="male">Male</option>
<option value ="female">Female</option>
</select>
This works ok.
If someone selects one of the options, I need to do something with the filtered results.
That's why I have a $watch in my controller that looks for changes to the filter query:
$scope.$watch('query.gender', function(newValue, oldValue) {
// Here is where I need to get filtered results
});
My question is:
How do I access the FILTERED content from the controller?
I'd like this preferably without having to do another "filtering" operation in the controller... (since the data was already filtered, the result is sitting somewhere in memory, right?)
You can simplify your code with the following:
<tbody>
<tr ng-repeat="person in (filteredPersons = (persons | filter:query))">
<td>{{person.name}}</td>
<td>{{person.gender}}</td>
</tr>
</tbody>
After that, you can get access to $scope.filteredPersons into controller or {{filteredPersons}} right into the view :)
I'm not entirely sure, but you can use the filter function in your controller. So try something like:
$scope.$watch('query.gender', function(newValue, oldValue) {
var x = $filter('filter')($scope.persons, $scope.query);
});
x should then contain the same filtered data as in your table I think. Have a look at the docs here: http://docs.angularjs.org/api/ng.filter:filter for some more info.

Resources