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

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.

Related

how to iterate json data using ng-repeat in angularjs

how to iterate json data using ng-repeat in angularjs
{
"CSS Corp":{
"COE":{"win_loss":[6,4]},
"YNOS":{"win_loss":[5,5]},
"ESTEE":{"win_loss":[10,0]},
"ELC":{"win_loss":[8,2]}
},
"SSSPL":{
"PEG":{"win_loss":[0,10]},
"ARUBA":{"win_loss":[2,8]},
"SALES":{"win_loss":[1,9]},
"MARKETING":{"win_loss":[7,3]}
},
}
Your question is very broad. You will first have to attach those JSON data to the scope of your controller and expose it to the template through a variable myData. Assuming you know how to do that, the use of ng-repeat becomes very trivial (add more columns or rows to fit your dataset):
<table>
<thead>
<tr><th>Header 1</th></tr>
</thead>
<tbody>
<tr ng-repeat="item in myData">
<td>{{ item }}</td>
</tr>
</tbody>
</table>
Use ng-repeat
Syntax : <tr ng-repeat="value in container">
Assuming that you have a array of JSON object in your JS as below,
var arrayObject = [
"CSS Corp":{
"COE":{"win_loss":[6,4]},
"YNOS":{"win_loss":[5,5]},
"ESTEE":{"win_loss":[10,0]},
"ELC":{"win_loss":[8,2]}
},
"SSSPL":{
"PEG":{"win_loss":[0,10]},
"ARUBA":{"win_loss":[2,8]},
"SALES":{"win_loss":[1,9]},
"MARKETING":{"win_loss":[7,3]}
}
];
Then your view should iterate as below,
<div ng-repeat="company in arrayObject">
{{company}} // use whatever you want to print
</div>

Angular: How to use ng-if inside ng-repeat within a table?

I'm looping through the properties of an object called an observation. One of those properties is ImageUrl. The ImageUrl is not important to the user and it's value is a Base64 image...so it's a mile long. I want to show all properties except the ImageUrl property. I'm trying to use ng-if to exclude it, but it's not working. Any tips? This is an old Angular 1 app at my work and I don't have any authority to upgrade it to Angular 2 or any other framework. I just need this ng-if to work or for someone to suggest an alternative that'd work. Thank you. This is my best try and it's not excluding ImageUrl. I can't get the ng-if to exclude anything.
<table>
<tbody>
<tr ng-repeat="p in properties(obs)">
<th ng-if="p !== 'ImageUrl'">{{p}}:</th>
<td ng-if="p !== 'ImageUrl'">{{obs[p]}}</td>
</tr>
</tbody>
</table>
The syntax would be:
<tr ng-repeat="(key, val) in obs">
<td ng-if="key !== 'ImageUrl'">{{val}}:</td>
<td ng-if="key === 'ImageUrl'">{{key}}</td>
</tr>
That way 'ImageUrl' will be shown in case of the ImageUrl property, else the value of the property.

Angular ng-repeat stay paged after filter

I'm using AngularJS and I have a simple table using ng-repeat and filter. When i insert anything at the search input it filters OK but it keeps paginated as it was before I filter the table. Any ideas why this is happening ?
Here's my code:
//some var initialization
$scope.pagina = {};
$scope.pagina.currentPage = 1,
$scope.pagina.numPerPage = 10,
$scope.pagina.maxSize = 5;
//return from server with data
coresFactory.getCores().then(function(response) {
$scope.tabelaCores = response.data;
$scope.filteredTodos = $scope.tabelaCores.cores.slice(0, 10);
});
//do pagination
$scope.$watch('pagina.currentPage', function() {
var begin = (($scope.pagina.currentPage - 1) * $scope.pagina.numPerPage),
end = begin + $scope.pagina.numPerPage;
$scope.filteredTodos = $scope.tabelaCores.cores.slice(begin, end);
},true);
<input ng-model="pesquisaTabela" type="search" style="width:300px;" class="form-control input-inline" placeholder="" aria-controls="sample_1"></label>
<table class="table" style="margin-bottom:5px;border:1px solid #DDDDDD" id="sample_1">
<thead>
<tr style="background-color:#F9F9F9">
<th style="width:100px; text-align:center;"> Id </th>
<th> Nome </th>
<th> Plural </th>
<th style="width:100px; text-align:center;"> Ativo </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="cor in filteredTodos | filter:pesquisaTabela" ng-click="setSelected(cor.id)" ng-class="{linhaSelected: cor.id === idCorSelecionada}">
<td style="text-align:center;"> {{cor.id}} </td>
<td style="text-transform:capitalize"> {{cor.nome}} </td>
<td style="text-transform:capitalize"> {{cor.plural}} </td>
<td style="text-align:center;">
<span ng-if="cor.status=='sim'" class="label label-sm label-success"> Sim </span>
<span ng-if="cor.status=='nao'" class="label label-sm label-danger"> Não </span>
</td>
</tr>
</tbody>
</table>
<pagination first-text="<<" last-text=">>" next-text=">" previous-text="<" ng-model="pagina.currentPage" total-items="tabelaCores.cores.length" max-size="pagina.maxSize" boundary-links="true"></pagination>
You have quite a disconnect between various parts
Pagination is working off of one array, display from another and filter from yet another because when filter kicks in it returns a new filtered array.
The way you have things structured, your filter won't work properly either.
When you slice the main data array the filter is only going to work on that part that is sliced....not the whole main array
In order for pagination to be synchronized with filtering your simplest start point would likely be do your own filtering and share the same filtered array between the pagination and the table.
There are some other built in filters that you could use also like limitTo that takes 2 arguments limit and begin. That would help you get rid of currrent slice
There are lots of available grid/table directives available.
Using one of those would be my best suggestion
There is one other way you could do this all in the view. There is a syntax for ng-repeat that creates a new filtered array on the scope and therefore gives you access to it's length
<tr ng-repeat="row in filteredData = ( data |filter:pesquisaTabela | limitTo:10:start)">
Using this you could pass filteredData array to the total-items of the pagination directive.
It also now lets you do things like:
<div> Filtered length is: {{filteredData.length}}</div>

Edit a filter with a simple checkbox

I would like to make an option for showing inactive users by checking a button.
Here is the users array:
$scope.users = [
{firstname: 'Paul', inactive: true},
{firstname: 'Mark', inactive: false},
{firstname: 'Maggie', inactive: false},
{firstname: 'Lucy', inactive: true}
];
And the table to display it:
<table>
<thead>
<th>Firstname</th>
<th>Activity</th>
</thead>
<tbody>
<tr ng-repeat="user in users | filter: ??">
<td>{{user.firstname}}</td>
<td>{{user.inactive}}</td>
</tr>
</body>
</table>
<input type="checkbox" ng-click="showInact()">Show inactives
I'm learning AngularJS, I didn't found an interesting way to do that. Can you help me finding a solution?
Thanks :)
Just do this way:
1) At you controller:
$scope.showInactive = false;
$scope.filterInact = function(item)
{
return item.inactive === $scope.showInactive;
};
$scope.showInact = function() {
$scope.showInactive = !$scope.showInactive;
}
2) Setup the filter:
<tr ng-repeat="user in users | filter:filterInact">
<td>{{user.firstname}}</td>
<td>{{user.inactive}}</td>
</tr>
I personally like using a filter function to filter data. This approach is flexible and can easily interact with your other form variables. From the angular docs, the filter expression can be a:
function(value, index): A predicate function can be used to write
arbitrary filters. The function is called for each element of array.
The final result is an array of those elements that the predicate
returned true for.
So an example filter function might look like this:
$scope.filterFunc = function (user) {
//if the checkbox is checked show everyone, else only those that aren't inactive
return $scope.showInactives || !user.inactive;
};
And the HTML would be changed to accommodate the filter function. Specifically, I'm binding the checkbox to a $scope variable ($scope.showInactives) that the filterFunc function uses in its logic. And of course the ng-repeat is using the function called filterFunc.
<input type="checkbox" ng-model="showInactives"/>Show inactive users
<br/>
<table>
<thead>
<tr>
<th>Firstname</th>
<th>Activity</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="user in users | filter:filterFunc">
<td>{{user.firstname}}</td>
<td>{{user.inactive}}</td>
</tr>
</tbody>
</table>
And if you need any other convoluted logic, the filter function allows you a lot of freedom. The only thing it needs to return is a boolean (true or false).
Demo.
Unrelated to filtering, I also had to fix the table's HTML by putting the <th> inside a table row <tr>.
Easiest Way !! You can set value of filter on click event.
<tr ng-repeat="user in users | filter:filters">
<td>{{user.firstname}}</td>
<td>{{user.inactive}}</td>
</tr>
on click filter set to check box
<input type="checkbox" ng-click="filters.inactive = true">
First, You need to set controller name instade of "myCtrl.js" whatever your controller name.

How to sort table by value using ng-if?

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/

Resources