ng-show when array length is zero - angularjs

I am a beginner for AngularJS. I am trying to display "No Tag Found" during filter process with the help of "ng-show".
JS:
function simpleController($scope)
{
$scope.tags = ['HTML','CSS','Jquery','Bootstrap','AngularJS'];
}
HTML:
<div ng-controller="simpleController">
<input class="txt" type="text" ng-model="nameText" />
<div>
<ul>
<li ng-repeat="myKeys in tags| filter:nameText">{{myKeys}}</li>
</ul>
<div ng-show="!tags.length">No Tag Found</div>
</div>
</div>
When I type any value other than array vales, I am not able to get "No Tag Found" using the above code. Please help. Thanks.

If you're filtering in your ng-repeat, you must apply the same filter for you ng-show. If you don't, the ng-show will always refer to the full array :
<div ng-show="!(tags| filter:nameText).length">No Tag Found</div>
Working fiddle : http://jsfiddle.net/HB7LU/3149/

Just better use ng-hide:
<div ng-hide="tags.length">No Tag Found</div>

<div class="box" ng-show="team_stores.length > 0" >
worked for me

easy way to create filter... demo is as below
var app = angular.module('myApp', []);
app.controller('myctrl', function ($scope) {
$scope.friends = [
{ name: "Peter", age: 20 },
{ name: "Pablo", age: 55 },
{ name: "Linda", age: 20 },
{ name: "Marta", age: 37 },
{ name: "Othello", age: 20 },
{ name: "Markus", age: 32 }
];
});
<!DOCTYPE html>
<html>
<head>
<title>welcome</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-app="myApp" ng-controller="myctrl">
Name: <input ng-model="filter" type="text" />
<ul>
<li ng-repeat="friend in friends |filter:filter">{{friend.name}}</li>
<li ng-show="!(friends| filter:filter).length">data not found</li>
<!--<link ng-repeat="friend in friends|filter:isActive ">-->
</ul>
</body>
</html>

Also you can try to use filter service, like this: $filter('filter')(array, expression, comparator), this service return new array.
you can see http://code.angularjs.org/1.2.16/docs/api/ng/filter/filter

Related

angular ng-repeat array show only one element

I have an array like this
$scope.mentors = [ {"name":"Jonathan", "status":0},
{"name": "Nathan","status":1},
{"name": "Chris","status":1},
{"name": "Brian","status":0}];
here my view code
<div ng-repeat="m in mentors">
<div ng-if="m.status == '1'">
<div>
{{m.name}}
</div>
</div>
</div>
and my result is :
Nathan and Chris
what can I do to just make it show Nathan or Chris
it must only show one result only
p/s: already try ng-show="$last" it did not work since Brian status is '0'
You can filter the array on statuses and then just take the first by checking against $index
angular.module('app', []).controller('myCtrl',function($scope){
$scope.mentors = [ {"name":"Jonathan", "status":0},
{"name": "Nathan","status":1},
{"name": "Chris","status":1},
{"name": "Brian","status":0}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html>
<body ng-app="app">
<div ng-controller="myCtrl">
<div ng-repeat="m in mentors | filter : {status: 1}">
<div ng-if="$index == 0">
<div>
{{m.name}}
</div>
</div>
</div>
</div>
</body>
</html>
You could use the limitTo and filter
<div ng-repeat="m in mentors | filter: { status : '1'}| limitTo : 1">
<div>
{{m.name}}
</div>
</div>
There is no reason to use ng-repeat if you only need to display 1 item.
You should handle this in your controller. Create a new variable that will hold the mentor that you want to show.
To find Nathan, you can use Array#find(). It will return the first item that matches the condition status === 1
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.mentors = [{
"name": "Jonathan",
"status": 0
},
{
"name": "Nathan",
"status": 1
},
{
"name": "Chris",
"status": 1
},
{
"name": "Brian",
"status": 0
}
];
$scope.mentor = $scope.mentors.find(m => m.status === 1);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<h1>{{mentor.name}}</h1>
</div>

How to assign default value in Dropdownboxlist?

Hi I am developing angularjs application. I tried many ways to set default value for dropdown in Angularjs but I am not able to set default value.
<select ng-change="getModel(b.ID)" ng-model="b.ID" id="brand" ng-options="b.MakeName for b in list">
<option value="1">-- Select a Make --</option>//Not working
</select>
<select ng-change="getStyle(a.ID)" ng-model="a.ID" ng-options="a.ModelName for a in Modellist" id="make" >
<option value="1">-- Select a Model --</option>
</select>//Not working
<select ng-change="getallDetails(c.ID)" id="type" ng-model="c.ID" ng-options="c.BodyStayleName for c in ModelStyle">
<option value="1">-- Select a Type --</option>
</select>//Not working
May I know am i missing here anything? Any help would be appreciated. Thank you.
Use ng-init or set the default value to the model variable inside the controller,
$scope.BrandId = "1";
DEMO
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
<script>
angular.module("myapp", [])
.controller("MyController", function($scope) {
$scope.register = {};
$scope.BrandId = "1";
$scope.brands = [{
id: "1",
name: "TOYOTA"
}, {
id: "2",
name: "HONDA"
}, {
id: "3",
name: "MARUTI"
}, {
id: "4",
name: "BMW"
}];
});
</script>
</head>
<body ng-app="myapp">
<div ng-controller="MyController">
<div>
<select ng-init="BrandId=='1'" ng-model="BrandId" ng-options="brand.id as brand.name for brand in brands"></select>
</div>
</div>
</body>
</html>

How can my ng-repeat not work on this small code

So currently I am following the course 'shaping up with angular.js', I quite like it so far but I am only on 1.5 'Built in Directives'. But I can't get my head around the ng-repeat what they using in the course.
So what you need to to do is just put ng-repeat on the div and it should loop through all items in the array and show them. Maby I mistyped something but I rewrote the thing 2 times and read it over like a 100 times.. :(
This is my current html template
<html lang="en" ng-app="store">
<body ng-controller="storeController as store">
<div ng-hide="store.product.soldOut" ng-repeat="product in store.products">
<h1>{{store.product.name}}</h1>
<h2>${{store.product.price}}</h2>
<p>{{store.product.description}}</p>
<button ng-show="store.product.canPurchase"> Add to cart </button>
</div>
</body>
</html>
And this is my app.js file.
(function () {
var app = angular.module('store', []);
app.controller('storeController', function () {
this.products = gems;
});
var gems = [
{
name: 'Dodecahedron',
price: 295,
description: 'Nice gem',
canPurchase: true,
soldOut: false
},
{
name: "Pentagonal Gem",
price: 5.95,
description: "more nice gems",
canPurchase: true,
soldOut: false
}
]
})();
I can't seems to find out why it isn't repeating itself. And I dont even know why in the course they say 'product in store.products' there is no 'product' called anywhere.
I put it in a codepen also
http://codepen.io/denniswegereef/pen/JYwora
Remove the "store" from your inline bindings. The moment you use ng-repeat you reference your data object from the in clause like this:
<div ng-hide="product.soldOut" ng-repeat="product in store.products">
<h1>{{product.name}}</h1>
<h2>${{product.price}}</h2>
<p>{{product.description}}</p>
<button ng-show="product.canPurchase"> Add to cart </button>
</div>
Your code is messy. Here is the correct version
var app = angular.module('store', []);
app.controller('storeController', function ($scope) {
$scope.products = [
{
name: 'Dodecahedron',
price: 295,
description: 'Nice gem',
canPurchase: true,
soldOut: false
},
{
name: "Pentagonal Gem",
price: 5.95,
description: "more nice gems",
canPurchase: true,
soldOut: false
}
];
});
<html lang="en" ng-app="store">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
</head>
<body ng-controller="storeController">
<div ng-repeat="product in products">
<div ng-hide="product.soldOut">
<h1>{{product.name}}</h1>
<h2>${{product.price}}</h2>
<p>{{product.description}}</p>
<button ng-show="product.canPurchase"> Add to cart </button>
</div>
</div>
</body>
</html>

Can I get the value from the key from ng-repeat x in xx | unique x.key

I have a collection of items that represent a grouping by one property. I want to create a list of items grouped by the value of this property and in each list present the value of this group once and then all the items that belong to the group.
Something like the following
<div ng-repeat="items in itemcollection | unique: 'groupkey'">
<h3>{{items.groupkey}}</h3>
<div ng-repeat="item in items">
<label>{{item.name}}</label>
</div>
</div>
So if I have a itemscollection like the following:
{{ groupkey: 1; name: 'Ada'}, { groupkey: 1; name: 'Beda'}, {groupkey: 2; name: 'Ceda'}}
So after the generation of divs and labels the result should be
<div>
<h3>1</h3>
<div><label>Ada</label></div>
<div><label>Beda</label></div>
</div>
<div>
<h3>2</h3>
<div><label>Ceda</label></div>
</div>
Is it possible to create this or do I need to handle the creating of the elements to better construct the data to make this happen?
This filter does what you want : https://github.com/a8m/angular-filter#groupby
Yes. Its possible by the combination of orderBy and filter function in angularJS. The following code will work :
var app = angular.module("myApp", []);
app.controller("lists", function($scope) {
$scope.list = [{
groupkey: 1,
name: 'Ada'
}, {
groupkey: 1,
name: 'Beda'
}, {
groupkey: 2,
name: 'Ceda'
}];
});
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.js"></script>
</head>
<body>
<div ng-controller="lists">
<div ng-repeat="items in list | orderBy:'groupkey'">
<h3>{{items.groupkey}}</h3>
<label>{{items.name}}</label>
</div>
</div>
</body>
</html>
Hope it works for you :)
Not tested but something like this I guess should work
<div ng-repeat="items in itemcollection | unique: 'groupkey'">
<h3>{{items.groupkey}}</h3>
<div ng-repeat="item in items | filter:{'groupkey': items.groupkey}:true">
<label>{{item.name}}</label>
</div>
</div>
If you make sure the itemcollection is sorted by groupkey you may display the groupkey header only when the groupkey differs from the previous groupkey. Then you achieve to only show the groupkey header once per group. Here is an example:
angular.module('myapp',[]).controller("thectrl", function($scope) {
$scope.itemcollection = [{ groupkey: 1, name: 'Ada'},
{ groupkey: 1, name: 'Beda'},
{groupkey: 2, name: 'Ceda'},
{groupkey: 2, name: 'D'}];
$scope.itemcollection.sort(function(a,b) { return a.groupkey-b.groupkey;});
});
The HTML:
<div ng-app="myapp" ng-controller="thectrl">
<div ng-repeat="item in itemcollection track by $index" >
<h3 ng-if="$index===0 || itemcollection[$index-1].groupkey!==item.groupkey">{{item.groupkey}}</h3>
<label>{{item.name}}</label>
</div>
</div>
And a working fiddle here:
https://jsfiddle.net/vuksyeyh/

AngularJS: Count Filtered Items

I am showing subsets of a list if a checkbox is checked. I would like to replace the X next to the checkbox with the count of the list matching the selection criteria. I have a plunker that does everything but count the subset here.
My Controller looks like this:
var app = angular.module('app', []);
app.controller('MainController', function($scope){
$scope.cbMarvel = true;
$scope.cbDCComics = true;
$scope.heroes = [
{
id: 1,
name: 'Iron Man',
fname: 'Tony',
lname: 'Stark',
location: 'Stark Tower',
comic: 'Marvel'
},
{
id: 2,
name: 'Batman',
fname: 'Bruce',
lname: 'Wayne',
location: 'Bat Cave',
comic: 'DC'
},
{
id: 3,
name: 'Superman',
fname: 'Clark',
lname: 'Kent',
location: 'Metroplis',
comic: 'DC'
},
{
id: 1,
name: 'Daredevil',
fname: 'Jack',
lname: 'Murdock',
location: 'Court Room',
comic: 'Marvel'
},
{
id: 5,
name: 'Flash',
fname: 'Barry',
lname: 'Allen',
location: 'Speedline',
comic: 'DC'
},
{
id: 6,
name: 'Hulk',
fname: 'Bruce',
lname: 'Banner',
location: 'Labratory',
comic: 'Marvel'
},
{
id: 7,
name: 'Hawkeye',
fname: 'Clint',
lname: 'Barton',
location: 'Nest',
comic: 'Marvel'
},
{
id: 8,
name: 'Thor',
fname: 'Donald',
lname: 'Blake',
location: 'Asgard',
comic: 'Marvel'
}
];
});
And my view looks like this:
<!DOCTYPE html>
<html ng-app="app">
<head>
<link data-require="bootstrap#*" data-semver="3.2.0" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.css" />
<link data-require="bootstrap-css#*" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
<script data-require="bootstrap#*" data-semver="3.2.0" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.js"></script>
<script data-require="jquery#2.0.3 current" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script data-require="angular.js#1.2.20" data-semver="1.2.20" src="https://code.angularjs.org/1.2.20/angular.js"></script>
<script data-require="angular-ui-bootstrap#*" data-semver="0.11.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="MainController">
<fieldset>
<legend>Comments Log</legend>
<div class="row">
<div class="col-md-4">
<input type="checkbox" ng-model="cbMarvel"/> Marvel [X]
</div>
<div class="col-md-4"> </div>
<div class="col-md-4">
<input type="checkbox" ng-model="cbDCComics"/> DC Comics [X]
</div>
</div>
<div class="row"> </div>
<div class="row col-md-10">
<div ng-if="heroes.length == 0"><b>No Heroes Found!</b>
</div>
<div ng-repeat="h in heroes | filter:{comic:'Marvel'}" ng-show="cbMarvel">
{{ h.name}} - {{h.comic}}
</div>
<div ng-repeat="h in heroes | filter:{comic:'DC'}" ng-show="cbDCComics">
{{ h.name}} - {{h.comic}}
</div>
</div>
</fieldset>
</body>
</html>
Assuming your list of people is in data variable and you filter people using query model, the following code will work for you:
Number of visible people: {{(data|filter:query).length}}
Total number of people: {{data.length}}
summary
{{data.length}} - prints total number of people
{{(data|filter:query).length}} - prints filtered number of people
You could set that count in the view model itself while binding the data or just have a method on the scope that returns the count.
app.controller('MainController', function($scope, filterFilter){
....
$scope.getCount = function(strCat){
return filterFilter( $scope.heroes, {comic:strCat}).length;
}
...
});
and use it as:-
Marvel [{{getCount("Marvel")}}]
.....
DC Comics [{{getCount("DC")}}]
Plnkr
If the list is non changing when you are on the page i would suggest finding out the length and binding it to a property in the view model itself, and use it in the view.
//Set your data model
$scope.cbMarvel = {value:true, count:getCount('Marvel')};
$scope.cbDCComics = {value:true, count:getCount('DC')};
and in your view
<input type="checkbox" ng-model="cbMarvel.value"/> Marvel [{{cbMarvel.count}}]
Plnkr2
If your dataset is huge, instead of using filter inside the getCount, use a forEach and populate the count for each type at once.
Infact you do not need a filter at all, it seems inefficient to iterate through the same list using a filter in your case. Your's is a static list so categorize it in the controller itself.
var comics = $scope.comics = {}; //Dictionary of comics
//Create the collection here.
angular.forEach(heroes, function(itm){
if(!comics[itm.comic]){
comics[itm.comic] = {name:itm.comic, value:true, count:1, items:[itm] };
return;
}
comics[itm.comic].count++; //Incr count
comics[itm.comic].items.push(itm); //push specific item
});
and remove all the filters in your view and do:-
<div ng-repeat="h in comics.Marvel.items" ng-show="comics.Marvel.value">
{{ h.name}} - {{h.comic}}
</div>
<div ng-repeat="h in comics.DC.items" ng-show="comics.DC.value">
{{ h.name}} - {{h.comic}}
</div>
Plnk3 - the better one
Possible solution 1: Inline
You could actually save a reference to the filtered results in a variable: h in filtered.marvel = (heroes | filter:{comic:'Marvel'}), which you could use like so: filtered.marvel.length.
See: Plunkr
Possible solution 2: In the controller
You could also move this code to your controller:
$scope.filteredHeroes.marvel = $filter('filter')($scope.heroes, {comic:'Marvel'});
, which you could use by ng-repeat="hero in filteredHeroes.marvel"
and {{filteredHeroes.marvel.length}}
(Don't forget to add $filter as a controller dependency)
See: Plunkr
To find the count objects, I use <scope_obj>.length in the .html template.
Here's my controller:
conciergeControllers.controller('GuestMsgPreviewCtrl', ['$scope', 'GuestMessages',
function($scope, GuestMessages) {
$scope.guests = GuestMessages.query();
}]);
And template (each guest object has a messages attribute that is an array object, so .length returns the number of nested message objects:
<ul ng-repeat="guest in guests">
<li>[[ guest.messages.length ]]</li>
</ul>

Resources