I am pretty new to angular and from documentation on official site and using plunkr I was able to figure out we use ng-repeat and push method to add something new to DOM if I am not wrong.
I am trying to go through this example found on docs:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-ngController-production</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<!--<script src="app.js"></script>-->
<script>
angular.module('controllerAsExample', [])
.controller('SettingsController1', SettingsController1);
function SettingsController1() {
this.name = "John Smith";
this.contacts = [
{type: 'phone', value: '408 555 1212'},
{type: 'email', value: 'john.smith#example.org'}
];
}
SettingsController1.prototype.greet = function () {
alert(this.name);
};
SettingsController1.prototype.addContact = function () {
this.contacts.push({ value: ''});
};
SettingsController1.prototype.removeContact = function (contactToRemove) {
var index = this.contacts.indexOf(contactToRemove);
this.contacts.splice(index, 1);
};
SettingsController1.prototype.clearContact = function (contact) {
contact.type = 'phone';
contact.value = '';
};
</script>
</head>
<body ng-app="controllerAsExample">
<div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
<label>Name: <input type="text" ng-model="settings.name"/></label>
<button ng-click="settings.greet()">greet</button><br/>
Contact:
<ul>
<li ng-repeat="contact in settings.contacts">
<select ng-model="contact.type" aria-label="Contact method" id="select_{{$index}}">
<option>phone</option>
<option>email</option>
</select>
<input type="text" ng-model="contact.value" aria-labelledby="select_{{$index}}" />
<button ng-click="settings.clearContact(contact)">clear</button>
<button ng-click="settings.removeContact(contact)" aria-label="Remove">X</button>
</li>
<li><button ng-click="settings.addContact()">add</button></li>
</ul>
</div>
</body>
</html>
This is kind basic overview I understood, but I am not able to figure out how ng-repeat is helping us to add a new element(push a new element). As far as I can see its acting like a iterator in java.
To do it the Angular way, you could have an array of text field meta values, e.g.
formFieldArr = [{fieldName: 'name', minLength: '2' ... } , {fieldName: 'gender', minLength: '4' ... }]
Have an ng-repeat to loop over and render the text fields.
In HTML
<div ng-repeat="formFieldArr">
<input name="formField.name" ng-minlength="formField.minLength">
</div>
In your submit codes, all you need is to add to the array and the form fields will be rendered.
FormFieldPost.save(){
onsuccess:
formFieldArr.push("{fieldName: 'gender', minLength: '4' ... }");
}
If you are thinking in terms of DOM, that will be more of a jQuery solution.
Expanding further, you could also use the same array to render different kinds of form fields.
formFieldArr = [{fieldName: 'name', minLength: '2', fieldType: 'select' ... } , {fieldName: 'gender', minLength: '4', fieldTypre: 'text' ... }]
In HTML
<div ng-repeat="formFieldArr">
<input name="formField.name" ng-minlength="formField.minLength" ng-show="formField.fieldType === 'text'">
... Do similar ng-show for select.
</div>
(Typing on mobile)
Related
var inputs={
'firstname': '',
'lastName':'',
'account':{
'role':'',
'status':''
}
}
This is my model array. I want to display it dynamically in Webpage and by modifying the json array the changes should affect the form too.
Here is the image
UPD:
for your situation, you can use ng-switch to generate elements according to conditions.
Notice(already included in the code snippet):
ng-repeat will generate it's own scope, so your model won't update unless you bind it with the original scope. ref here.
OLD ANSWER:
use ng-model to implement two-way-databinding.
refer the code snippet below:
angular.module("app", []).controller("myCtrl", function($scope) {
$scope.inputs = {
'firstname': 'test first name',
'lastName': 'test last name',
'account': {
'role': 'test role',
'status': 'test status'
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.4/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<!-- First Name: <input type="text" ng-model="inputs.firstname"><br>
Last Name: <input type="text" ng-model="inputs.lastName"><br> Account Role: <input type="text" ng-model="inputs.account.role"><br>
Account Status: <input type="text" ng-model="inputs.account.status"><br> -->
<div ng-repeat="(key1, value) in inputs" ng-switch="key1">
<div ng-switch-when="account">
<div ng-repeat="(key2, value2) in value">
{{key1 | uppercase}} => {{ key2 | uppercase}}
<input type="text" ng-model="inputs[key1][key2]">
</div>
</div>
<div ng-switch-default>
{{key1 | uppercase}}
<input type="text" ng-model="inputs[key1]">
</div>
</div>
{{inputs}}
</div>
/My html should look like this/
<head>
<script data-require="angular.js#1.4.1" data-semver="1.4.1" src="https://code.angularjs.org/1.4.1/angular.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="MainCtrl">
<script type="text/ng-template" id="tree-structure">
<label>{{dt}}</label><input type="text" name="" value="{{dt.label}}">
<ul class="childElement">
<li ng-repeat="dt in dt.nodes" ng-include="'tree-structure'">
</li>
</ul>
</script>
<ul class="parentList">
<li ng-repeat="(key, value) in inputs" >
<div ng-repeat="(key1, value1) in value">
<label>{{key1}}</label>
<input type="text" name="" value="{{value1}}">
<!-- <div ng-repeat="(key2, value2) in value1">
<label>{{key2}}</label><input type="text" name="" value="{{value2}}">
</div> -->
</div>
<div ></div>
</li>
</div>
</ul>
</body>
</html>
Some observations :
Your JSON should be formatted properly with type of the field.
If you want to access the object properties as a form fields then it should be structured in a good way so that we can dynamically add the type of the field as well.
[{
name: 'firstName',
type: 'text'
}, {
name: 'lastname',
type: 'text'
}, {
account: [{
name: 'role',
type: 'text'
}, {
name: 'status',
type: 'text'
}]
}]
As your JSON have nested objects. So, first iterate it recursively and create one dimensional array then create the fields using 1D array.
DEMO
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function($scope) {
var inputs = [{
name: 'firstName',
type: 'text'
}, {
name: 'lastname',
type: 'text'
}, {
account: [{
name: 'role',
type: 'text'
}, {
name: 'status',
type: 'text'
}]
}];
$scope.fields = [];
function structuredObj(obj) {
for (var i in obj) {
if (obj[i].type == 'text') {
$scope.fields.push(obj[i]);
} else {
structuredObj(obj[i])
}
}
};
structuredObj(inputs);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<form name="myForm" novalidate>
<div ng-repeat="item in fields" class="form-group">
<input
name="item.name"
type="{{ item.type }}"
placeholder="{{ item.name }}"
ng-model="item.value"
required />
</div>
<button ng-disabled="myForm.$invalid">Submit</button>
</form>
</div>
<div ng-repeat="(key1, value1) in myPersonObj">
<div ng-repeat="(key, value) in value1">
<label>{{key}}</label>
<input type="text" name="" value="{{value}}">
</div>
</div>
var app = angular.module("test",[]);
app.controller("MainCtrl",function($scope){
$scope.inputs = [
{
"firstname" : "Test"
},{
"lastname" : "Test1"
},{
"Account" : [
{"role" : "Test3"},
{"status" : "Test4"},
]
},
{
"Account1" : [
{"role" : "Test3"},
{"status" : "Test4"},
]
},
{
"Account2" : [
{"role" : {
'dim3': {
'dim4':{
'dim5':'cccc'
}
}
}
},
{"status" : "Test4"},
]
}
];
$scope.person = [];
$scope.myPersonObj = [];
/*console.log($scope.keys(inputs));*/
$scope.checkIndex1 = function(arg, myPersonObj)
{
if (angular.isArray(arg) || angular.isObject(arg)) {
angular.forEach(arg, function (value, key) {
console.log(value);
if(angular.isObject(value) || angular.isArray(value))
{
$scope.checkIndex1(value, myPersonObj);
}
else
{
console.log("pushing");
myPersonObj.push(arg);
}
});
}
else
{
console.log("pushing1");
myPersonObj.push(arg);
}
}
$scope.checkIndex1($scope.inputs, $scope.myPersonObj);
console.log("myPersonObj :"+ JSON.stringify($scope.myPersonObj));
console.log($scope.inputs);
I'm very much new to angularjs so I'm facing this issue where i have a nested json, and i am using the parent value as a header and the values of the child as checkboxes. Now, when I want to retrieve the value of those checkboxes which have been ticked, i want it in the format of {parent_name:child_name} stored in an array.
I'm using the following sample data taken from this thread.
Data:
parents : [{
name: 'George',
age: 44,
children: [{
name: 'Jack',
age: 16,
isChecked: 'true'
},{
name: 'Amy',
age: 13,
isChecked: 'false'
}]
}, {
name: 'Jimmy',
age: 38,
children: [{
name: 'Max',
age: 7,
isChecked: 'false'
},{
name: 'Lily',
age: 5,
isChecked: 'false'
},{
name: 'Kim',
age: 4,
isChecked: 'true'
}]
}]
And, my current output
looks like this
My HTML code is
<div class="col-md-12 col-xs-12" ng-repeat="parent in parents ">
<div class="form-group">
<label>{{parent.name}}</label>
<div class="input-group" ng-repeat="child in parent.children">
<label><input type="checkbox" ng-checked="child.isChecked=='true'"> {{child.name}}</label>
</div>
<hr>
</div>
Now, in reference to the image, I want to have {George:Jack} and {Jimmy:Kim} in an array, but i can't find a way to achieve that.
EDIT : I forgot to mention another important point, some checkboxes will be pre-selected. As per the data, checkbox for Jack and Kim will already be ticked on-load. I have to fetch the value for the pre-selected values as well as any newly checked checkboxes.
My Plunker code is here.
I hope my question is clear. Thanks in advance!
The proposed solution modifies your original JSON object.
If for some reasons, you have to keep the original JSON object, you should do a copy of it and store it in the controller scope (Angular has functions to do it).
The idea is to add a isChecked attribute in the original JSON object which will be values to false by default and that will be set to true when the checkbox is selected or false when the checkbox is unselected.
That is possible by using the ng-model directive which binds here a html input to a variable in JS side.
Here is the plunker :
http://plnkr.co/edit/EzDp3mMtlnH3t4bIz8e6?p=preview with Angular js 1.5.
js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.parents = [{
name: 'George',
age: 44,
children: [{
name: 'Jack',
age: 16,
isChecked: true;
},{
name: 'Amy',
age: 13
}]
}, {
name: 'Jimmy',
age: 38,
children: [{
name: 'Max',
age: 7
},{
name: 'Lily',
age: 5
},{
name: 'Kim',
age: 4,
isChecked: true;
}]
}]
$scope.submit= function(){
var results = [];
for (var i=0; i< $scope.parents.length; i++){
var parent = $scope.parents[i];
for (var j=0; j< parent.children.length; j++){
var child = parent.children[j];
if (child.isChecked){
results.push(parent.name +":"+ child.name);
}
}
}
//display info
for ( i=0; i< results.length; i++){
console.log(results[i]) ;
}
}
});
html
<!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://code.angularjs.org/1.5.8/angular.js" data-semver="1.5.8"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<div class="col-md-12 col-xs-12" ng-repeat="parent in parents ">
<div class="form-group">
<label>{{parent.name}}</label>
<div class="input-group" ng-repeat="child in parent.children">
<label><input type="checkbox" ng-checked="child.isChecked=='true'" ng-model="child.isChecked">
{{child.name}}</label>
</div>
<hr>
</div>
</div>
<button type="button" ng-click="submit()" class="btn btn-success width-80px">Submit</button>
</body>
</html>
Using the ngChecked directive, you can only mark the checkbox as checked if the expression (here child.checked=='true') is truthy. However, it doesn't affect the value of your variable child.checked.
I recommand you to use instead the ngModel directive which will bind the value of your checkbox with child.checked (or any other variable).
<div class="col-md-12 col-xs-12" ng-repeat="parent in parents ">
<div class="form-group">
<label>{{parent.name}}</label>
<div class="input-group" ng-repeat="child in parent.children">
<label>
<input type="checkbox" ng-model="child.checked">{{child.name}}
</label>
</div>
<hr>
</div>
Since child.checked is not defined at the begining, it will be falsy so the checkbox won't be checked. You can change this behaviour by setting it to true.
Then, to create an array of your results, you can do something like this:
var results = [];
parents.forEach(function (parent) {
parent.children.forEach(function (child) {
if (child.checked) {
var couple = {};
couple[parent.name] = child.name;
results.push(couple);
}
});
});
I am fetching data from API and I need a searchable dropdown so that when I start typing it shows me the data coming from the API. Currently I have this piece of code.
<select class="formControl" name="repeatSelect" id="repeatSelect" ng-model="facilitiesData.business_id">
<option ng-repeat="option in businesses" value="{{option.id}}">{{option.business_name}}</option>
</select>
Thanks.
Probably you are looking for this. This could be one of the solution.
This has different type of typeaheads. You can pick one as per your needs.
<input type="text" ng-model="customPopupSelected" placeholder="Custom popup template" uib-typeahead="state as state.name for state in statesWithFlags | filter:{name:$viewValue}" typeahead-popup-template-url="customPopupTemplate.html" class="form-control">
Note - You will require a library ui-bootstrap-tpls which is officially created by AngularJS team.
Try this. you cannot directly put textbox inside option and filter select based on it. but this is one way that you can don so. another way is to use plugin or angular material design.
// Angular
var myApp = angular.module('app', []);
myApp.controller('ListCtrl', function($scope) {
$scope.items = [{
'name': 'Item 1'
}, {
'name': 'Item 2'
}, {
'name': 'Account 3'
}, {
'name': 'Account 4'
}, {
'name': 'Item 5'
}, {
'name': 'Item 6'
}, {
'name': 'User 7'
}, {
'name': 'User 8'
}];
});
// jQuery
$('.dropdown-menu').find('.dontClose').click(function(e) {
e.stopPropagation();
});
.dropdown.dropdown-scroll .dropdown-menu {
max-height: 200px;
width: 60px;
overflow: auto;
}
.search-control {
padding: 5px 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<div class="dropdown dropdown-scroll" ng-app="app">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown">Select <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1" ng-controller="ListCtrl">
<li role="presentation" class="dontClose">
<div class="input-group input-group-sm search-control">
<span class="input-group-addon">
<span class="glyphicon glyphicon-search"></span>
</span>
<input type="text" class="form-control" placeholder="Query" ng-model="query"></input>
</div>
</li>
<li role="presentation" ng-repeat='item in items | filter:query'> {{item.name}}
</li>
</ul>
</div>
you can use datalist tag also If you want to build your own searchable dropdown ..Here is the working code:
HTML Part:
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-controller="myCtrl">
<form ng-submit="click(search);">
<label class="child-label" for="existing-phases">Existing: </label>
<input type="text" ng-model="search" list="names">
<datalist id="names" class="form-control" ng-model="name">
<option value=''>-- select an option --</option>
<option ng-repeat="option in contacts | filter:search | limitTo:3" value="{{option.name}}"></option>
</datalist>
<button type="submit">Submit</button>
</form>
</div>
</body>
</html>
JS Part:
var app = angular.module('app', []);
app.controller('myCtrl', function($scope) {
$scope.showContacts = function() {
$scope.contacts = [{
id: 1,
name: "Ben",
age: 28
}, {
id: 2,
name: "Sally",
age: 24
}, {
id: 3,
name: "John",
age: 32
}, {
id: 4,
name: "Jane",
age: 40
}];
};
$scope.showContacts();
$scope.click = function(MyData) {
alert(JSON.stringify(MyData));
};
});
Working Demo is available here..https://plnkr.co/edit/hamW3F05YUPrWwS3RmmG?p=preview
You're in the right path. All you need to do now is create an http service or factory that triggers an API call every keypress, and the result of which populates your $scope.businesses array.
If you want to build searchable drop-down on your own then you can make use of filters.searchable drop-down with filters using textbox
If you want to go for a plugin check angular multi select
I've recenlty used in one of my projects. It is a flexible plugin and it allows multi-select also.
You can use dropdown select plugin
JS
const app = angular.module('DropdownSelectApp', ['DropDownSelect']);
HTML
<dropdown-select dd-model="exampleModel" dd-data="exampleItemList" dd-label="labelName" >
See this like for demo: https://saravanajd.github.io/Angularjs-Dropdown-Search/
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>
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>