Angular controller not displaying object array data - angularjs

This is not displaying data, I am learning about controllers. Why it is not displaying data while it displays data in the video I am watching.
<div data-ng-controller="FirstController">
<input type="text" name="txtName" data-ng-model="typedName" />
<br />
Typed Name is: {{ typedName }}
<br />
Names:
<ul >
<li data-ng-repeat="person in Customers | orderBy:'name' | filter:typedName "> {{ person.name | uppercase}} - {{ person.city }}
</li>
</ul>
</div>
<script>
function FirstController($scope) {
$scope.Customers = [
{ name: 'Sita', city: 'Los Angeles' },
{ name: 'Ram', city: 'Los Vegas' },
{ name: 'Amit', city: 'San Antonio' },
{ name: 'Cat', city: 'Arkanas' },
{ name: 'Boushick', city: 'Pittsburgh' }
];
}
</script>
<script src="Scripts/angular.min.js"></script>

Looks like you're following older videos where they mmight be using angular 1.2.
In latest version of angular, it's mandatory to specific app name and declare controllers under those modules. Though you can activate global controller functions via config but its not recommended.
So you need to make the following changes:
In your HTML,
<html data-ng-app="myApp">
NOw in your JS for controller:
angular.module("myApp", [])
.controller("ControllerName", function($scope) {
// declare your $scope data here
})
Why global controller functions are deprecated?
When you declare controller functions globally, It will be polluting the global namespace. Assume there is another library which is using the same function name, then your function would be overriden.
For example,
you have function SimpleController in your file. Assume some third party library you're using, they also use same name for some functionality.
They set,
window.SimpleController = window.alert
So it means your controller function has been overriden.
that's why it's been deprecated.

From the code you provided I believe its not working because you have not declared an Angular Module in your javascript and linked it to your html view via ng-app. Please check the working Plunker below.
http://plnkr.co/edit/fwwzZwODfZ9G5Ml1Y1MS?p=preview
<body ng-app="myApp">
<div ng-controller="FirstController">
<input type="text" name="txtName" ng-model="typedName" />
<br />
Typed Name is: {{ typedName }}
<br />
Names:
<ul>
<li data-ng-repeat="person in Customers | orderBy:'name' | filter:typedName ">
{{ person.name | uppercase}} - {{ person.city }}
</li>
</ul>
</div>
<script>
angular.module('myApp', [])
.controller('FirstController', function($scope) {
$scope.Customers = [
{ name: 'Sita', city: 'Los Angeles' },
{ name: 'Ram', city: 'Los Vegas' },
{ name: 'Amit', city: 'San Antonio' },
{ name: 'Cat', city: 'Arkanas' },
{ name: 'Boushick', city: 'Pittsburgh' }
];
});
</script>
</body>

Related

Understanding basics of controller in AngularJS

I'm still very basic with AngularJS (and programming in general honestly speaking. Having watched some videos online, I'm trying to understand the controller concept with the below example (e.g. passing an array and then iterating through it with ng-repeat). Have gone over this for the past hour and it works without the controller (e.g. with the array), but not when adding the array in a seperate script. Can anyone help me find my error in logic here - it literally is the same as the video, but I cannot see the error (or even a typo) and feel this is so fundamental, I should have this working, before moving on to the next steps.
Many thanks for any of your help:
<html ng-app>
<head><title>My First Page</title></head>
<body >
<div class="container" ng-controller="SimpleController">
Name:
<br />
<input type="text" ng-model="name" />
<br />
<ul>
<li ng-repeat="cust in customers"> {{ cust.name }} </li>
</ul>
</div>
<script src="script/angular.min.js"></script>
<script>
function SimpleController($scope) {
$scope.customers = [
{ name: 'Simon', lastname: 'Test' },
{ name: 'Thomas', lastname: 'Testi' },
{ name: 'Adi', lastname: 'Testo' },
{ name: 'Adrian', lastname: 'Testo' },
{ name: 'Tomeli', lastname: 'Testi' }
];
}
</script>
</body>
</html>
You are using global declaration of controller which is with angular 1.1 version. If you use version above 1.3 , you should declare the controller as follows,
var app = angular.module('testApp',[]);
app.controller('testCtrl',function($scope){
$scope.customers = [
{ name: 'Simon', lastname: 'Test' },
{ name: 'Thomas', lastname: 'Testi' },
{ name: 'Adi', lastname: 'Testo' },
{ name: 'Adrian', lastname: 'Testo' },
{ name: 'Tomeli', lastname: 'Testi' }
];
});
DEMO
var app = angular.module('testApp',[]);
app.controller('SimpleController',function($scope){
$scope.customers = [
{ name: 'Simon', lastname: 'Test' },
{ name: 'Thomas', lastname: 'Testi' },
{ name: 'Adi', lastname: 'Testo' },
{ name: 'Adrian', lastname: 'Testo' },
{ name: 'Tomeli', lastname: 'Testi' }
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="testApp">
<div class="container" ng-controller="SimpleController">
Name:
<br />
<input type="text" ng-model="name" />
<br />
<ul>
<li ng-repeat="cust in customers"> {{ cust.name }} </li>
</ul>
</div>
</body>

ng-repeat is not creating list item in an unordered list

What is the mistake in my code? cust.name and cust.city are not displaying.
Why are no list items created?
<html>
<body>
<div data-ng-controller="SimpleController">
Name :
<br />
<input type="text" data-ng-model="name" placeholder="Enter Your Name " /> {{ name }}
<br />
<ul>
<li data-ng-repeat="cust in customers | filter:name | orderBy:'city' ">
{{ cust.name | uppercase }} - {{ cust.city | lowercase }}
</li>
</ul>
</div>
<script src="angular.min.js"></script>
<script>
function SimpleController($scope) {
$scope.customers = [
{
name: 'Rishabh Shrivas',
city: 'New Delhi'
},
{
name: 'Rishabh Bharadawaj',
city: 'Noida'
},
{
name: 'Rishabh Sen',
city: 'Gurgaon'
}
];
}
</script>
</body>
</html>
You need an ng-app section in the HTML, even an empty one is sufficient. Also, you need to create the controller differently:
var myApp = angular.module('myApp',[]);
myApp.controller('SimpleController', ['$scope', function($scope) {
$scope.customers = [
{
name: 'Rishabh Shrivas',
city: 'New Delhi'
},
{
name: 'Rishabh Bharadawaj',
city: 'Noida'
},
{
name: 'Rishabh Sen',
city: 'Gurgaon'
}
];
}]);

How to implement PhoneJS SlideOut with AngularJS?

I tried the following code:
var app = angular.module('app', ['ngRoute', 'dx'])
app.controller('IndexCtrl', function($scope){
var contacts = [
{ name: "Barbara J. Coggins", phone: "512-964-2757", email: "BarbaraJCoggins#rhyta.com", category: "Family" },
{ name: "Carol M. Das", phone: "360-684-1334", email: "CarolMDas#jourrapide.com", category: "Friends" },
{ name: "Janet R. Skinner", phone: "520-573-7903", email: "JanetRSkinner#jourrapide.com", category: "Work" }
];
$scope.slideOutOptions = {
dataSource: contacts,
itemTemplate: 'item',
menuItemTemlate: 'menuItem'
}
})
<!-- HTML -->
<div class="app-index" ng-controller="IndexCtrl">
<div dx-slideout="slideOutOptions">
<div data-options="dxTemplate: { name: 'item' }">
<h1 data-bind="text: category"></h1>
<p><b>Name:</b> <span data-bind="text: name"></span></p>
<p><b>Phone:</b> <span data-bind="text: phone"></span></p>
<p><b>e-mail:</b> <span data-bind="text: email"></span></p>
</div>
<div data-options="dxTemplate: { name: 'menuItem' }">
<b data-bind="text: name"></b>
</div>
</div>
</div>
AngularJS there is not enough documentation on the DevExpress site. there are only examples using Knockout. Checkout PhoneJS DXSlideOut Documentation
The problem is in the HTML templates. You should use Angular syntax there.
<div dx-slideout="slideOutOptions">
<div data-options="dxTemplate: { name: 'item' }">
<h1>{{category}}</h1>
<p><b>Name:</b> <span>{{name}}</span></p>
<p><b>Phone:</b> <span>{{phone}}</span></p>
<p><b>e-mail:</b> <span>{{email}}</span></p>
</div>
<div data-options="dxTemplate: { name: 'menuItem' }">
<b>{{name}}</b>
</div>
</div>
Checkout docs about Angular approach.

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>

ng-show when array length is zero

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

Resources