How filter in a view - angularjs

i have this Code in my view
<div ng-repeat="config in configs">
<div ng-repeat="test in tests ">
{{test[config.Name]}}</li>
</div>
</div>
it works fine. But how can I filter test?
<div ng-repeat="test in Tests | filter:{[config.Name]:'Test'} ">
dont work. How can I filter the column config.Name?
Thanks for your Help
Stefan

Add that function to your controller:
$scope.createFilter = function(property, value) {
var result = {};
result[property] = value;
return result;
};
and use it in the view:
<div ng-repeat="test in Tests | filter: createFilter(config.Name, 'Test')">

Try this, I hope that could help you:
JS :
$scope.conf = [];
$scope.conf.Name = 'Test';
HTML:
<div ng-repeat="config in configs | filter:conf:strict">
<div ng-repeat="test in tests ">
{{test[config.Name]}}</li>
</div>
</div>

That's a tricky one, but if you put the filter value in a variable first that might work?
<div ng-repeat="config in configs" ng-init="$filter = {}; $filter[config.Name] = 'Test'}">
<div ng-repeat="test in tests | filter : $filter">
{{test[config.Name]}}</li>
</div>
</div>

Related

Filter the object in the array by dynamic filter - AngularJS

Right now my data structure is like
product = [{att1:'2',att2:'red',att3:'gold'},
{att1:'1',att2:'blue',att3:'wood'},
{att1:'2',att2:'green',att3:'plastic'},
{att1:'1',att2:'red',att3:'plastic'}]
And I have a filter on the web page, it has three parts: att1, att2, att3. The user doesn't have to choose options for every part.
For filter att1 it has 2 options: "1" and "2".
Filter att2 it has 2 options: "red" "blue" and "green"
Filter att3 it has 3 options: "gold", "wood" and "plastic".
I can get the options that are selected. For example:
{att1:['2'],att3:['gold','plastic']} or {att1:['1']}
My question is, how do I use product.filter to filter the product data?
Thanks!
You can use a custom filter function which is easy to use, I used att1 but you can expand it to all fields:
var app = angular.module("MyApp", []);
app.controller("MyCtrl", function($scope) {
$scope.products = [{att1:'2',att2:'red',att3:'gold'},
{att1:'1',att2:'blue',att3:'wood'},
{att1:'2',att2:'green',att3:'plastic'},
{att1:'1',att2:'red',att3:'plastic'}];
$scope.filterFunction = function(element) {
return element.att1.match(/^Ma/) ? true : false;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyApp">
<div ng-controller="MyCtrl">
<form class="form-inline">
<input ng-model="query" type="text"
placeholder="Filter by" autofocus>
</form>
<ul ng-repeat="product in products | filter:query">
<li>{{product}}</li>
</ul>
<ul ng-repeat="product in products | filter:filterFunction">
<li>{{product}}</li>
</ul>
</div>
</div>
I banged out the particular logic for this one, using the three nested loops isn't super great but it does do the job. I'm sure you can optimize this further by using some maps or something but I just went with the get it done by brute force approach :)
angular.module('myApp',[])
.service('ProductService', function(){
return {
products:[
{att1:'2',att2:'red',att3:'gold'},
{att1:'1',att2:'blue',att3:'wood'},
{att1:'2',att2:'green',att3:'plastic'},
{att1:'1',att2:'red',att3:'plastic'}
]
}
})
.controller('TestCtrl', function(ProductService){
this.ProductService = ProductService;
this.filterObject1 = {att1:['2'],att3:['gold','plastic']};
this.filterObject2 = {att1:['1']};
})
.filter('productFilter', function(){
return function(input,filterObj){
if(!filterObj){
return input;
}
var newArray = [];
var filterKeys = Object.keys(filterObj);
for(var i=0;i<input.length;i++){
var curElement = input[i];
innerLoops:
for(var j=0;j<filterKeys.length;j++){
var curKey= filterKeys[j];
for(var k=0;k<filterObj[curKey].length;k++){
var curFilterValue = filterObj[curKey][k];
if(curElement[curKey].match(curFilterValue)){
//We found a match keep this element and move on to checking the next one by breaking out of the inner loops that are checking particular keys/values
newArray.push(curElement);
break innerLoops;
}
}
}
}
return newArray;
};
})
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.js"></script>
<div ng-app="myApp" ng-controller="TestCtrl as ctrl">
Unfiltered
<div ng-repeat="product in ctrl.ProductService.products|productFilter">
{{product}}
</div>
<hr/>
<strong>Filtered with: {{ctrl.filterObject1}}</strong>
<div ng-repeat="product in ctrl.ProductService.products|productFilter:ctrl.filterObject1">
{{product}}
</div>
<hr/>
<strong>Filtered with {{ctrl.filterObject2}}</strong>
<div ng-repeat="product in ctrl.ProductService.products|productFilter:ctrl.filterObject2">
{{product}}
</div>
</div>

How to limit results with ng-repeat?

Sorry for the basic question, extremely new to software development and angular in particular. I'm currently making a small app that uses an api to find cinemas near a certain postcode.
I have made a results page that show what films are playing in a certain cinema, but I want to limit the amount of results returned and include a 'Show more films' button.
I have included my html and controller below:
HTML
<div class="main-container">
<fountain-header></fountain-header>
<div class="cinemas-container">
<h2 align="center" class="cinemas-h2">Movies playing here:</h2>
<div class="cinema2" ng-repeat="listing in $ctrl.listings">
<h3 class="cinema-h5">{{listing.title}}</h3>
<ul class="cinema-h4">
<li ng-repeat="time in listing.times">{{time}}</li>
</ul>
</div>
<div class="main-container">
</main>
</div>
<fountain-footer></fountain-footer>
</div>
</div>
ListingsController
function ListingsController($http, $stateParams) {
console.log($stateParams);
console.log($stateParams.cinemaID);
var vm = this;
$http
.get('https://api.cinelist.co.uk/get/times/cinema/' + $stateParams.CinemaID +'?day=1')
.then(function (response) {
console.log(response);
vm.listings = response.data.listings;
});
}
Could I just use limitTo to achieve this?
P.S sorry for the poor information, it's my first question on here.
Please try the following example in the fiddle link -
Using the limitTo filter.
ng-repeat="d in data | limitTo: limitvar"
https://jsfiddle.net/m0q9ju8a/
let me know if this helps.
You can do like this:
HTML
<div class="main-container">
<fountain-header></fountain-header>
<div class="cinemas-container">
<h2 align="center" class="cinemas-h2">Movies playing here:</h2>
<div class="cinema2" ng-repeat="listing in vm.listings | limitTo: vm.limit as results">
<h3 class="cinema-h5">{{listing.title}}</h3>
<ul class="cinema-h4">
<li ng-repeat="time in vm.listing.times">{{time}}</li>
</ul>
</div>
<button ng-hide="results.length === vm.listings.length" ng-click="vm.limit = vm.limit +8">show more...</button>
<div class="main-container">
</main>
</div>
<fountain-footer></fountain-footer>
</div>
</div>
and in youn controller
function ListingsController($http, $stateParams) {
console.log($stateParams);
console.log($stateParams.cinemaID);
var vm = this;
vm.limit = 8;
$http
.get('https://api.cinelist.co.uk/get/times/cinema/' + $stateParams.CinemaID +'?day=1')
.then(function (response) {
console.log(response);
vm.listings = response.data.listings;
});
}

angularjs: can't dynamically set filter method with scope data

In my angular application, I came into a filter related issue. I have reproduced this issue with a simple live demo as bellow:
https://jsfiddle.net/baoqger/fpo3j6gx/2/
<div ng-app="app">
<div ng-controller="filterCtrl as f">
<input type="text" ng-model="f.inputdata"></input>
<span ng-click="f.setFilter('lowercase')">First Filter</span>
<span ng-click="f.setFilter('uppercase')">Second Filter</span>
<div ng-bind="f.inputdata | f.filtername"></div>
</div>
click First Filter or Second Filter will trigger the setFilter function.
function filterCtrl() {
this.setFilter = function ( name ){
this.filtername = name;
}.bind(this);
}
angular
.module('app', [])
.controller('filterCtrl', filterCtrl)
In the controller, the filtername will be set to lowercase or upper case, depends on which button was clicked as mentioned above.
Then set the filtername as filter method as below:
<div ng-bind="f.inputdata | f.filtername"></div>
But based on the error message, it seems that angular system can't support such usage. Any help?
Try this solution:
Javascript:
.controller('filterCtrl', ['$filter' function($filter){
var self = this;
self.setFilter = function(name){
self.filter = $filter(name);
}
}]);
HTML:
<div ng-app="app">
<div ng-controller="filterCtrl as f">
<input type="text" ng-model="f.inputdata"></input>
<span ng-click="f.setFilter('lowercase')">First Filter</span>
<span ng-click="f.setFilter('uppercase')">Second Filter</span>
<div ng-bind="f.filter?f.filter(f.inputdata):f.inputdata"></div>
</div>

NG-Repeat with NG-show Not executing with dynamic data

Im trying to get a client list and detail view to work but i cant seem to figure it out. The NG-init wont work nor will the ng-click, I can get it to work if its hard coded, but when dynamically loading data it wont work. Id appreciate if anyone can point out the correct way to execute this.
html:
<div ng-controller="ClientCtrl as clients">
<table class="listview">
<tbody>
<tr ng-repeat="stuff in clients.records">
<td><a ng-click="client = {{$index}}" class="client-link">{{stuff.first_name}} {{stuff.last_name}}</a></td>
</tr>
</tbody>
</table>
<div class="detailview">
<div ng-repeat-start="things in clients.records " ng-if="$first">
<div id="contact-{{$index}}" class="tab-pane active" ng-show="client == {{$index}}" ng-init="client = {{$index}}">
<h2>{{things.first_name}} {{things.last_name}}</h2>
</div>
</div>
<div ng-repeat-end="things in clients.records " ng-if="!$first">
<div id="contact-{{$index}}" class="tab-pane active" ng-show="client == {{$index}}" ng-init="client = {{$index}}">
<h2>{{things.first_name}} {{things.last_name}}</h2>
</div>
</div>
</div>
</div>
controller.js:
function ClientCtrl($scope,$http,$interval, $rootScope){
var ClientCtrlData = this;
$http.get("api/clients").success(function(response) {
ClientCtrlData.records = response.records;
});
var promise;
// simulated items array
$scope.items = [];
// starts the interval
$scope.start = function() {
// stops any running interval to avoid two intervals running at the same time
$scope.stop();
// store the interval promise
promise = $interval(
function(){
$http.get("api/clients").success(function(response) {
ClientCtrlData.records = response.records;
console.log("People loaded");
});
}.bind(this)
,1000000 * 10);
};
// stops the interval
$scope.stop = function() {
$interval.cancel(promise);
};
// starting the interval by default
$scope.start();
$scope.$on('$destroy', function() {
$scope.stop();
});
}
angular
.module('inspinia')
.controller('ClientCtrl',ClientCtrl)
plnkr http://plnkr.co/edit/yzN787uL6C82Z6g6JNOq
First off, no need to use ng-click="client = {{$index}}", you're already saying that the code should be parsed by angular so no need for the angular brackets {{ }}.
Second, you need to scope client inside ng-click="client = $index" for example as such ng-click="clients.client = $index", otherwise angular doesn't know where to look for the property.
I also wonder what the need for the ng-init is? I'm guessing this is just mock functionality, because now it will just set the clients.client variable for each item until it ends up being the last one in the list.
In any case, here's a version of your code with fixed syntax, you should be able to take it from here
http://plnkr.co/edit/UyKYvxpErcehizSBKaqy?p=preview
<div ng-controller="ClientCtrl as clients">
<table class="listview">
<tbody>
<tr ng-repeat="stuff in clients.records">
<td>
<a ng-click="clients.client = $index" class="client-link">{{stuff.first_name}} {{stuff.last_name}}</a>
</td>
</tr>
</tbody>
</table>
<div class="detailview">
<div ng-repeat="things in clients.records ">
<div id="contact-{{$index}}" class="tab-pane active" ng-show="clients.client == $index" ng-init="clients.client = $index">
<h2>{{things.first_name}} {{things.last_name}}</h2>
</div>
</div>
</div>
</div>

ng-repeat filter on boolean

I am trying to filter on a boolean value in an ng-repeat.
List of unregistered users:
<h3>Unregistered Users</h3>
<div ng-repeat="user in users | filter:!user.registered">
<div class="row-fluid">
<div class="span2">
{{user.name}}
</div>
</div>
</div>
List of registered users:
<h3>Registered Users</h3>
<div ng-repeat="user in users | filter:user.registered">
<div class="row-fluid">
<div class="span2">
{{user.name}}
</div>
</div>
</div>
Is there a good way to filter based on registered and !registered.
filter by obj expression:
<h3>Unregistered Users</h3>
<div ng-repeat="user in users | filter:{registered:false}">
<div class="row-fluid">
<div class="span2">
{{user.name}}
</div>
</div>
</div>
JSFiddle: http://jsfiddle.net/alfrescian/9ytDN/
Create a method in the controller which returns true or false based on the logic you need and specify that function in the filter.
Something like this:
$scope.isRegistered = function(item) {
return item.registered;
};
<h3>Unregistered Users</h3>
<div ng-repeat="user in users | filter:!isRegistered ">
<div class="row-fluid">
<div class="span2">
{{user.name}}
</div>
</div>
</div>
In case an item does not have a boolean property set, you can find the item with a property not set to true by using '!' with quotes. e.x. filter: {property:'!'+true}.
Example:
$scope.users = [
{
name : 'user1 (registered)',
registered : true
},
{
name : 'user2 (unregistered)'
},
{
name : 'user3 (registered)',
registered : true
},
{
name : 'user4 (unregistered)'
}
To get unregistered users filter:
<h3>Unregistered Users</h3>
<div ng-repeat="user in users | filter:{registered:'!'+true}">
<div class="row-fluid">
<div class="span2">
{{user.name}}
</div>
</div>
</div>
Had the same question. Alfrescian solution didn't work for me on Angular 1.1.5.
Found this fiddle: http://jsfiddle.net/buehler/HCjrQ/
.filter('onlyBooleanValueFilter', [function(){
return function(input, param){
var ret = [];
if(!angular.isDefined(param)) param = true;
angular.forEach(input, function(v){
// 'active' is a hard-coded field name
if(angular.isDefined(v.active) && v.active === param){
ret.push(v);
}
});
return ret;
};
}])
You would need to adjust the code of the filter according to your field.
Slight modification to Websirnik's answer, this allows any column name for the dataset:
.filter('onlyBooleanValueFilter', [function () {
return function (input, column, trueOrFalse) {
var ret = [];
if (!angular.isDefined(trueOrFalse)) {
trueOrFalse = false;
}
angular.forEach(input, function (v) {
if (angular.isDefined(v[column]) && v[column] === trueOrFalse) {
ret.push(v);
}
});
return ret;
};
}])
Markup:
<div repeat="row in your.dataset | onlyBooleanValueFilter: 'yourColumn' : true">
...your stuff here....
</div>

Resources