I'm trying to make a filter with the angularJs directive called ng-repeat the filter works as follows:
When you click on the checkbox filters in an array the items that have offers, I'm using a function to filter, I think there is a better way to do it without so much code.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http, $document) {
$scope.items = [
{
id: 0,
description: "Primer Item 1",
offers: [
{
id: 0,
name: "Casa"
}
]
},
{
id: 1,
description: "Segundo Item 2"
},
{
id: 2,
description: "Tercer Item 3"
},
{
id: 3,
description: "Cuarto Item 4"
},
{
id: 4,
description: "Quinto Item 5"
},
{
id: 5,
description: "Sexto Item 5",
offers: [
{
id: 1,
name: "Bodega"
}
]
},
{
id: 6,
description: "Septimo Item 6"
},
{
id: 7,
description: "Octavo Item 7"
},
{
id: 8,
description: "Noveno Item 8"
},
{
id: 9,
description: "Decimo Item 9"
}
];
$scope.filterItem = function() {
if (!$scope.itemOffer){
$scope.filterOffer = function(item) {
return item.offers && item.offers.length > 0;
};
$scope.itemOffer = true;
} else {
$scope.filterOffer = function(item) {
return item;
};
$scope.itemOffer = false;
}
};
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<input type="checkbox" name="filter" value="propertyOffer" ng-model="propertyOffer" ng-click="filterItem()">Item with offert
<div ng-repeat="item in items | filter: filterOffer track by $index">
{{ item }}
</div>
</body>
</html>
You can use ng-if with the ng-repeat directive to filter items containing offers at will :
JS CODE
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http, $document) {
$scope.offersOnly = false;
$scope.items = [
// Your items
];
});
HTML CODE
<body ng-app="myApp" ng-controller="myCtrl">
<input type="checkbox" ng-model="offersOnly" ng-true-value="true" ng-false-value="false"/>
<div ng-repeat="item in items" ng-if="!offersOnly">
{{item}}
</div>
<div ng-repeat="item in items" ng-if="offersOnly && item.offers">
{{item}}
</div>
</body>
Related
I am new in angular js i want to put filter in ng-repeat i have json like this
var data = [
{name:test1,b1:{lastValue:0},b2:{lastValue:6},b3:{lastValue:6},b4:{lastValue:0}}
{name:test2,b1:{lastValue:6},b2:{lastValue:0},b3:{lastValue:6},b4:{lastValue:0}}
{name:test3,b1:{lastValue:6},b2:{lastValue:0},b3:{lastValue:6},b4:{lastValue:0}}
]
I want to put filter on lastValue i tested like this
ng-repeat = "d in data | filter:{*.lastValue:filterStatus}"
filterStatus // contain value of filter which user selected but its not working
I don't know how to do this i tried google but nothing found please help me
<input ng-model="filterStatus" type="text">
your filterStatus should hold model value
ng-repeat = "d in data | filter:filterStatus"
var app = angular.module("Profile", []);
app.controller("ProfileCtrl", function($scope) {
$scope.filter_val = {}
$scope.data = [{
name: 'test1',
b1: {
lastValue: 0
},
index: 'b1'
}, {
name: 'test2',
b2: {
lastValue: 6
},
index: 'b2'
}, {
name: 'test3',
b3: {
lastValue: 6
},
index: 'b3'
}, {
name: 'test4',
b4: {
lastValue: 0
},
index: 'b4'
}, {
name: 'test5',
b5: {
lastValue: 89
},
index: 'b5'
}, {
name: 'test6',
b6: {
lastValue: 68
},
index: 'b6'
}]
$scope.own_filter = function(val) {
if (!$scope.filter_val.value)
return true;
else {
return (String(val[val['index']]['lastValue'] || '').indexOf($scope.filter_val.value) != -1)
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="Profile" ng-controller="ProfileCtrl">
<input type="text" ng-model="filter_val.value" placeholder="Enter Last Value">
<div class="row" ng-repeat="event in data |filter:own_filter track by $index ">
<h4>{{'Name : ' + event.name}}------{{'Last Value : '+event[event['index']]['lastValue']}}</h4>
</div>
</body>
Use {$:filterStatus} construction:
angular.module('app', []).controller('ctrl',function($scope){
$scope.data = [
{name:'test1',b1:{lastValue:1},b2:{lastValue:6},b3:{lastValue:6},b4:{lastValue:0}},
{name:'test2',b1:{lastValue:2},b2:{lastValue:0},b3:{lastValue:6},b4:{lastValue:0}},
{name:'test3',b1:{lastValue:3},b2:{lastValue:0},b3:{lastValue:6},b4:{lastValue:0}}
]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js">
</script>
<div ng-app='app' ng-controller='ctrl'>
<input type='number' ng-model='filterStatus' ng-init='filterStatus=1'>
<ul>
<li ng-repeat='item in data | filter: {$:filterStatus}'>{{item.name}}</li>
</ul>
</div>
i listed category from json data.i have listed number of sub category under category but i want to list only 3 sub category under category.if i click view more option i want to list corresponding sub category depends on category in modal popup.
i have returned created div depends on parentid zero
$scope.cat = categories.filter(function(category) {
return category && category.parentid === 0
});
i have updated my code in plunker.
http://plnkr.co/edit/Vh1NzYf0qjUkIygLUEJk?p=preview
You can do it by simlpe filter:
<div ng-repeat="childItem in content | filter: item.id | limitTo: 3">
Demo 1 plunker
It also will get rid of using ng-if="childItem.parentid === item.id"
Example:
<div ng-repeat="item in cat">
{{item.name}}
<div ng-repeat="childItem in content | filter: item.id | limitTo: 3">
<div style="margin-left: 20px;" >
{{childItem.name}}
</div>
</div>
</div>
If you want to handle view more, you can write:
<div ng-repeat="childItem in content | filter: item.id | limitTo: limit">
and:
$scope.limit = 3;
$scope.viewMore = function(){
$scope.limit = 100;
}
Demo 2 plunker
[EDIT]
if you want to update view more per sub-category, you need bind limit to your data:
<body ng-controller="MainCtrl">
<div ng-repeat="item in cat">
{{item.name}}
<div ng-repeat="childItem in content | filter: item.id | limitTo: item.limit">
<div style="margin-left: 20px;" >
{{childItem.name}}
</div>
</div>
<a href="" ng-click="viewMore(item)"
ng-if="item.limit == 3">view more</a>
</div>
</body>
and:
$scope.viewMore = function(item){
item.limit = 100;
}
Demo 3 plunker
Update
If you want a show more functionality refer the below Plunkr.
Plunkr
This will do the job. I have added a custom filter that takes the parent.Id as an argument and check the child's parent Id (which was done before by the ng-if). Then I use angular's limit to: 3 filter to limit the results to only 3 items.
Plunkr
Code:
$scope.searchMe = function(statusId) {
return function(user) {
return user.parentid === statusId;
}
}
and the ng-repeat should look like
<div ng-repeat="item in cat">
{{item.name}}
<div ng-repeat="childItem in content | filter: searchMe(item.id) | limitTo: 3">
<div style="margin-left: 20px;">
{{childItem.name}}
</div>
</div>
<a ng-click="open_modalpopup()">view more</a>
</div>
References:
Limit To
passing arguements to angularJS filters
UPDATE -
As per your latest requirement -
if i click view more i want to list all corresponding sub category
depends on category
I update the plnkr to show all categories in a popup once user clicked on View More button.
Updated Plnkr - http://plnkr.co/edit/OUvzqWdfZuQnZpbXWSRW?p=preview
As per your requirement I believe you need to show/hide sub categories on the basis of button click available under specific category.
I re arranged your data and rather than saving it into multiple objects, I am using a singular object newcat to store and manage the UI.
Working Plnkr -
http://plnkr.co/edit/F6MlkMWOJ2b7isRAM1u6?p=preview
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var data = [{
id: 1,
name: 'mobile',
parentid: 0
}, {
id: 2,
name: 'samsung',
parentid: 1
}, {
id: 3,
name: 'moto',
parentid: 1
}, {
id: 4,
name: 'redmi',
parentid: 1
}, {
id: 5,
name: 'honor',
parentid: 1
}, {
id: 6,
name: 'nokia',
parentid: 1
},
{
id: 7,
name: 'tv',
parentid: 0
}, {
id: 8,
name: 'tv1',
parentid: 7
}, {
id: 9,
name: 'tv2',
parentid: 7
}, {
id: 10,
name: 'tv3',
parentid: 7
}, {
id: 11,
name: 'tv4',
parentid: 7
}, {
id: 12,
name: 'tv5',
parentid: 7
}];
var categories = data;
$scope.title = 'Show Hide Subcategories';
$scope.cat = categories.filter(function(category) {
return category && category.parentid === 0
});
$scope.newcat = angular.extend($scope.cat, {});
angular.forEach($scope.cat, function(cat, key){
var tmpIndex = 0;
var tmpdata = categories.filter(function(category) {
if(cat.id === category.parentid) {
category.indexVal = tmpIndex;
category.isShow = tmpIndex < 3 ? true : false;
tmpIndex++;
return true;
}
})
$scope.newcat[key]['subCat'] = tmpdata;
$scope.newcat[key]['moreclicked'] = false;
})
$scope.showMore = function(index) {
if(!$scope.newcat[index]['moreclicked']) {
angular.forEach($scope.newcat[index].subCat, function(subcat, key) {
subcat.isShow = true;
})
$scope.newcat[index]['moreclicked'] = true;
}
else {
angular.forEach($scope.newcat[index].subCat, function(subcat, key) {
if(key > 2)
subcat.isShow = false;
})
$scope.newcat[index]['moreclicked'] = false;
}
};
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<h3 ng-bind="title"></h3>
<div ng-repeat="cat in newcat">
<b>{{cat.name}}</b>
<div ng-repeat="subcat in cat.subCat">
<div style="margin-left: 20px;" ng-if="subcat.isShow">
{{subcat.name}}
</div>
</div>
<button ng-click="showMore($index)" ng-bind="!cat.moreclicked ? 'View More': 'View Less'"></button>
</div>
</body>
</html>
Here, I used $watch to display the counter value.
But the counter value not increased yet,
To Count,
$scope.$watch('items', function(items){
var selectedItems = 0;
angular.forEach(items, function(item){
selectedItems += item.selected ? 1 : 0;
})
$scope.selectedItems = selectedItems;
}, true);
In UI,
<div class="col-sm-4" ng-repeat="item in items">
<label class="chkbox-holder cbox mbot10" for="List-{{$index}}"><input ng-model="item.Selected" type="checkbox" id="List-{{$index}}"><label for="List-{{$index}}"></label>{{item.name}}</label>
</div>
To display the counter value,
<div>Selected Items Length: {{selectedItems}}</div>
But still the counter is 0;
JSON Value from http service is,
[
{
"id": 1,
"refCode": "",
"name": "pragadees"
},
{
"id": 2,
"refCode": "",
"name": "pragadees"
}......]
Can anyone please help on this.
You've just got a typo error. Your markup is bound to item.Selected while your JavaScript is checking for item.selected. Renaming them properly solves your problem. I'd recommend using lower key inside ot html.
<input ng-model="item.selected" type="checkbox" id="List-{{$index}}">
^-- See here
Demo
first of all, you got a typo in your ng-model, it is item.selected not item.Selected that's maybe why it does not match nothing...
And this is how i'll write it, using basic angular two way data binding, no extra counters, watches, triggers, ....
angular.module('myApp', []);
angular.module('myApp').controller('Ctrl', ['$scope', function($scope) {
$scope.items = [{
name: "Doe"
}, {
name: "Adam"
}, {
name: "Ado"
}, {
name: "Brown"
}, {
name: "Heather"
}, {
name: "Stan"
}];
$scope.itemsSelected = function() {
return $scope.items.filter(function(i) {
return i.selected
}).length;
}
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="Ctrl">
<h2>current active selected options {{ itemsSelected() }}</h2>
<ul>
<div ng-repeat="item in items">
<label for="List-{{$index}}">
<input ng-model="item.selected" type="checkbox" id="List-{{$index}}">
<label for="List-{{$index}}"></label>{{item.name}}</label>
</div>
</ul>
</body>
You can use ng-change instead:
var app = angular.module("app", []);
app.controller("myCtrl", function($scope) {
$scope.items = [
{name: 'A', value: 'a'},
{name: 'B', value: 'b'},
{name: 'C', value: 'c'},
{name: 'D', value: 'd'},
{name: 'E', value: 'e'}
];
$scope.counter = 0;
$scope.change = function(e) {
if(e){
$scope.counter +=1;
}else{
if($scope.counter > 0) $scope.counter -=1;
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<div class="col-sm-4" ng-repeat="item in items">
<label class="chkbox-holder cbox mbot10" for="List-{{$index}}">
<input ng-model="item.Selected" type="checkbox" id="List-{{$index}}"
ng-change="change(item.Selected)">
<label for="List-{{$index}}"></label>{{item.name}}</label>
</div>
Counter: {{counter}}
</div>
I am trying to insert a node dynamically, but the appended html is not getting compiled correctly.
This is the code on Fiddle.
<body ng-app="app">
<div ng-controller="appController">
{{tittle}}
<div name="name" ng-repeat="d in data" ng-click="click(d.id)" id="div{{d.id}}">{{d.id}} click me</div>
</div>
(function () {
var app = angular.module('app', []);
app.controller('appController', function ($scope, $compile) {
$scope.tittle = "test";
$scope.data = [{ id: 1, child: [{name:'renjith'}] }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }];
$scope.click = function (data, $element) {
debugger;
var scope = { id: "12" };
angular.element(document.querySelector("#div" + data)).append($compile("<div ngTransclude>{{d.id}}</div>")($scope.data));
}
});
})();
I use Angular, this is my view:
<div class="col-sm-6" ng-repeat="contact in service.contacts">
<label class="control-label mb10">{{contact.textDescription | decodeURIComponent}}</label>
<select multiple="multiple" selectize>
<option>{{contact.value}}</option>
</select>
</div>
I have one problem and I can't figure out a way to solve it. For contact.textDescription, I need to put only unique values, so if that contact.textDescription is duplicate, don't create field twice, but add that contact.value to options of that same contact.textDescription which already exists.. So, something like this:
if(contact.textDescription is duplicate) {
contact.value.addTo(contact.textDescription which already exists)
}
Maybe some filter to apply or?
By the understanding of what you mentioned I think the filter mention in the following answer will help you to do what you want
Use this link to go to the question
You can use ng-options to group and display unique value.
You can use uniqFilter of angular-filter module.
Usage: collection | unique: 'property' or nested.property
Aliases: uniq
Example:
JS:
function MainController ($scope) {
$scope.orders = [
{ id:1, customer: { name: 'John', id: 10 } },
{ id:2, customer: { name: 'William', id: 20 } },
{ id:3, customer: { name: 'John', id: 10 } },
{ id:4, customer: { name: 'William', id: 20 } },
{ id:5, customer: { name: 'Clive', id: 30 } }
];
}
HTML:
<th>Customer list:</th>
<tr ng-repeat="order in orders | unique: 'customer.id'" >
<td> {{ order.customer.name }} , {{ order.customer.id }} </td>
</tr>
RESULT:
Customer list:
- John 10
- William 20
- Clive 30
Grouping your contacts by textDescription should resolve your problem. Try something like this:
html:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - GroupBy Filter</title>
<script src="angular-1.4.7.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="app">
<div ng-controller="MainController">
<div ng-repeat="(key, contacts) in (service.contacts | groupBy: 'textDescription')">
<label class="control-label">{{key}}</label>
<select multiple="multiple" selectize>
<option ng-repeat="contact in contacts">{{contact.value}}</option>
</select>
</div>
</div>
</body>
script.js:
var app = angular.module("app", []);
app.controller("MainController", function ($scope) {
$scope.service = {};
$scope.service.contacts = [{
"textDescription": "td1",
"value": "1"
}, {
"textDescription": "td2",
"value": "2"
}, {
"textDescription": "td3",
"value": "3"
}, {
"textDescription": "td1",
"value": "4"
}, {
"textDescription": "td3",
"value": "5"
}, {
"textDescription": "td1",
"value": "6"
}];
});
app.filter('groupBy', function () {
var results={};
return function (data, key) {
if (!(data && key)) return;
var result;
if(!this.$id){
result={};
}else{
var scopeId = this.$id;
if(!results[scopeId]){
results[scopeId]={};
this.$on("$destroy", function() {
delete results[scopeId];
});
}
result = results[scopeId];
}
for(var groupKey in result)
result[groupKey].splice(0,result[groupKey].length);
for (var i=0; i<data.length; i++) {
if (!result[data[i][key]])
result[data[i][key]]=[];
result[data[i][key]].push(data[i]);
}
var keys = Object.keys(result);
for(var k=0; k<keys.length; k++){
if(result[keys[k]].length===0)
delete result[keys[k]];
}
return result;
};
});
Now you have all the contacts grouped by textDescription, so the field for it (<label>) is created only once and the values are added to <option> tags