I want to fetch the list of friends for the REST-API into table using $http.get method in angularjs. Please see the DEMO.
I am not able to load the JSON data, When I click on button.
JSON.data
{
"friends": [
{
"FirstName": "John",
"LastName": "Doe"
},
{
"FirstName": "Ann",
"LastName": "Wellington"
},
{
"FirstName": "Sabrina",
"LastName": "Burke"
}
]
}
Index.html
<body ng-app="step4App">
<div ng-controller="FriendsCtrl">
<button ng-click="loadFriends()">Load Friends</button>
<table>
<thead>
<tr><th>First</th><th>Last</th></tr>
</thead>
<tbody>
<tr ng-repeat="friend in friends">
<td>{{friend.FirstName}}</td>
<td>{{friend.LastName}}</td>
</tr>
</tbody>
</table>
</div>
<script>
var app=angular.module("step4App",[]);
app.controller("FriendsCtrl", function($scope, $http){
$scope.loadFriends=function(){
$http.get("friendsList.json").success(function(data){
$scope.friends=data;
}).error(function(){
alert("An unexpected error occured!");
});
}
});
</script>
</body>
Your JSON file have an object, and $scope.friends is an array.
You need change this:
$scope.friends=data;
to:
$scope.friends = data.friends;
DEMO
Related
I am testing AngularJS. I am trying to read a json file with http.get and show it in a ng-repeat.
I have two problems...
First, the file with .json extension is not recognized. I have to rename it with .js extension
Second, the format elements in the file are not recognize. Repeater is filled with empty rows.
Here is my Angular.html
<!DOCTYPE html>
<html ng-app="exampleApp">
<head>
<title>Ajax</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="angular.js"></script>
<link href="bootstrap.css" rel="stylesheet" />
<link href="bootstrap-theme.css" rel="stylesheet" />
<script>
angular.module("exampleApp", [])
.controller("defaultCtrl", function ($scope, $http) {
$scope.loadData = function () {
$http.get("productData.js").success(function (data) {
$scope.products = data;
});
}
});
</script>
</head>
<body ng-controller="defaultCtrl">
<div class="panel panel-default">
<div class="panel-body">
<table class="table table-striped table-bordered">
<thead><tr><th>Name</th><th>Category</th><th>Price</th></tr></thead>
<tbody>
<tr ng-hide="products.length">
<td colspan="3" class="text-center">No Data</td>
</tr>
<tr ng-repeat="item in products">
<td>{{name}}</td>
<td>{{category}}</td>
<td>{{price | currency}}</td>
</tr>
</tbody>
</table>
<p>
<button class="btn btn-primary" ng-click="loadData()">
Load Data
</button>
</p>
</div>
</div>
</body>
</html>
Here is my ProductData.js
[{ "name": "Apples", "category": "Fruit", "price": 1.20, "expiry": 10 },
{ "name": "Bananas", "category": "Fruit", "price": 2.42, "expiry": 7 },
{ "name": "Pears", "category": "Fruit", "price": 2.02, "expiry": 6 },
{ "name": "Tuna", "category": "Fish", "price": 20.45, "expiry": 3 },
{ "name": "Salmon", "category": "Fish", "price": 17.93, "expiry": 2 },
{ "name": "Trout", "category": "Fish", "price": 12.93, "expiry": 4 }]
What I am doing wrong?
Thanks.
Rename your file as productdata.json. and change your code according to it
angular.module("exampleApp", [])
.controller("defaultCtrl", function ($scope, $http) {
$scope.loadData = function () {
$http.get("productData.json").success(function (data) {
$scope.products = data;
});
}
});
Also if you are using angularjs version above 1.3 replace .Success with .Then, because .Success has been deprecated
I have found why it does not appear... It was my mistake.. I had to replace
<tr ng-repeat="item in products">
<td>{{name}}</td>
<td>{{category}}</td>
<td>{{price | currency}}</td>
</tr>
for this one
<tr ng-repeat="item in products">
<td>{{item.name}}</td>
<td>{{item.category}}</td>
<td>{{item.price | currency}}</td>
</tr>
I have forgotten to add item.
Anyway.. I could not find why my PC do not accept .json file... If I put those file in IIS directory and run it from IIS, it Works fine.. But it does not work from outside IIS.
I am using DataTables ajax to fill a table. I was following this example and it works if my json looks like their example, however my 'data' is a nested object in my json and then it is not able to fill the table because fails in getting the values from the json.
This json works:
{
"data": [
{"id": "myid1", "name": "name1"},
{"id": "myid2", "name": "name2"}
]
}
But my json looks like this, and it does not work
{
"result": {
"data": [
{"id": "myid1", "name": "name1"},
{"id": "myid2", "name": "name2"}
]
}
}
That's my html (which works with the first json):
<table id="myTable" class="tabletable-bordered dataTable">
<thead>
<tr>
<th>name</th>
<th>id</th>
</tr>
</thead>
<tbody>
<td></td>
<td></td>
</tbody>
</table>
And that's my js:
$('#myTable').DataTable( {
"ajax": "/names",
"processing": true,
"dataSrc" : "result.data",
"columns": [
{ "data": "name" },
{ "data": "id" }
]
} );
As you can see I try to access to my nested data by setting dataSrc to result.data, but nothing is shown in the table.
I cannot change the format of the json response, do you know if then is not possible to use DataTables ajax with this json? Thanks!
MY SOLUTION
Finally (before getting an answer to my post) I went with the following solution, I first make an ajax call and then on success I create my DataTable.
so I only changed my js to this one:
$.ajax({
type: "GET",
url: '/names',
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (data) {
var myData = data.result.data;
$('#myTable').DataTable({
"data": myData,
"columns": [
{ "data": "id" },
{ "data": "name"},
]
});
}
});
I had more complex processing requirements so I implemented my own ajax function but I think you can get away with this:
$('#myTable').DataTable( {
"processing": true,
"ajax": {
"url": "/names",
"dataSrc" : function(jsonObj) {
// Just being safe here
if(!jsonObj.results || !json.results.data) {
return [];
}
return jsonObj.results.data;
}
},
"columns": [
{ "data": "name" },
{ "data": "id" }
]
});
Here is the reference for this: https://datatables.net/reference/option/ajax
I have been stuck on displaying data with ng-repeat. the only thing I have been able to do is display the one of the two objects. Every Customer can have multiple Users. I am trying to display the Users in a table with there CustomerId.
Working plunkr
app.controller('MainCtrl', function ($scope) {
var json = [
{
"CustomerId": "12xsd-344-fv23", "CompanyName": "ConocoPhillips",
"Address": "1234 Main St", "City": "Redmond", "State": "WA", "Zip": "10999",
"Email": "debra#example.com",
"Users": [
{
"FirstName": "Rudy", "LastName": "Sanchez", "CustomerId": "12xsd-344-fv23", "Customer": null,
"Email": "admin#energy.com", "EmailConfirmed": true, "PasswordHash": "AGtuCXr",
"SecurityStamp": "b0fca140", "PhoneNumber": null, "PhoneNumberConfirmed": false, "TwoFactorEnabled": false,
"LockoutEndDateUtc": null, "LockoutEnabled": false, "AccessFailedCount": 0, "Roles": [], "Claims": [], "Logins": [],
"Id": "49b5", "UserName": "admin"
},
{
"FirstName": "Troy", "LastName": "Benbow", "CustomerId": "12xsd-344-fv23", "Customer": null,
"Email": "tbenbow#yahoo.com", "EmailConfirmed": true, "PasswordHash": "AM8wL+iHaSG",
"SecurityStamp": "14f1483a-2e6f-41da-8307-a6c5945984a9", "PhoneNumber": null, "PhoneNumberConfirmed": false, "TwoFactorEnabled": false,
"LockoutEndDateUtc": null, "LockoutEnabled": true, "AccessFailedCount": 0, "Roles": [], "Claims": [], "Logins": [],
"Id": "9985b820-a45", "UserName": "tbenbow"
}
]
},
];
$scope.customers = json;
});
Since, CustomerId is also a property of User, you could make a list of Users in the controller and then loop them in the table:
$scope.users = [];
for(var i = 0; i < $scope.customers.length; i++) {
for(var j = 0; j < $scope.customers[i].Users.length; j++) {
//now you have access to customer properties with $scope.customers[i]
var user = $scope.customers[i].Users[j];
//example of adding CompanyName property
user.CompanyName = $scope.customers[i].CompanyName;
//add user to $scope.users
$scope.users.push(user);
}
}
And then just ng-repeat the users:
<tr ng-repeat="user in users">
<td>{{user.FirstName}} {{user.LastName}}</td>
<td>{{user.UserName}}</td>
<td>{{user.Email}}</td>
<td>{{user.CustomerId}}</td>
<td>{{user.CustomerName}}</td>
</tr>
Here is an updated plunker.
In fact, even if you need a property on the parent Customer part of json, you can add the property to the users array being repeated.
Preparing the data for view will often simplify template tricks (like having to build the table with extra ng-repeated elements. IMO, this is preferable.
There are two possible solutions for this problem, the first one ( rearranging your data in your controller) has already been mentioned in the other answer.
Another way would be a nested loop which I implemented like this:
<!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 src="http://code.angularjs.org/1.1.4/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>UserName</th>
<th>Email</th>
<th>CustomerId</th>
</tr>
</thead>
<tbody ng-repeat="customer in customers">
<tr ng-repeat="user in customer.Users">
<td>{{user.FirstName}} {{user.LastName}} {{customer.CustomerId}}</td>
<td>{{user.UserName}}</td>
<td>{{user.Email}}</td>
<td>{{user.CustomerId}}</td>
</tr>
</tbody>
</table>
</body>
</html>
This solution is fast and easy to implement and gives you access to both the user and customer. I would still suggest to rebuild your data in your controller most of the time as it keeps your views clean and keeps any real logic in your controller (Check here for an example of that).
But this example is so simple that you can easily handle it in a nested ng-repeat.
Here is the full code.
HTML part:
<script id="company_template" type="text/x-handlebars-template">
{{#each CDataMap}}
<div>{{this}}</div>
{{/each}}
<p></p>
</script>
JS part
var source = $("#company_template").html();
var template = Handlebars.compile(source);
var data= {
"CDataMap" : {
"name": "Jim Cowart",
"location": {
"city": {
"name": "Chattanooga",
"population": 167674
},
"state": {
"name": "Tennessee",
"abbreviation": "TN",
"population": 6403000
}
},
"company": "appendTo"
}
};
$("p").append(template(data));
I want to use this using handlebars js.
When am using it am getting object object display only.
I need the correct code.
The problem with your example is that CDataMap is not an array of objects, so you cannot iterate through them.
This is a valid example:
<script>
(function ($) {
$(function () {
var source = $("#company_template").html();
var template = Handlebars.compile(source);
var data = {
"CDataMap": [{
"name": "Jim Cowart",
"location": {
"city": {
"name": "Chattanooga",
"population": 167674
},
"state": {
"name": "Tennessee",
"abbreviation": "TN",
"population": 6403000
}
},
"company": "appendTo"
}]
};
$("p").append(template(data));
});
})(jQuery);
</script>
And also the p tag or any element you'll use to put the result in must be outside of the template, like this:
<script id="company_template" type="text/x-handlebars-template">
{{#each CDataMap}}
<div>{{this.name}}</div>
<div>{{this.location.city.name}}</div>
{{/each}}
</script>
<p></p>
Handlebar each expects iterative elements. Data which you are supplying needs to be modified.
Below code works
<script id="company_template" type="text/x-handlebarstemplate">
{{#each CDataMap}}
<div>Name : {{this.name}} <br/>
Location: {{this.location.city.name}} <br />
Population: {{this.location.city.population}}
</div>
{{/each}}
</script>
<p></p>
JS side
var data= {
"CDataMap" : [
{
"name": "Jim Cowart",
"location": {
"city": {
"name": "New york",
"population": 494949494
}
}
},
]
};
var templateSource = $("#company_template").html();
template = Handlebars.compile(templateSource);
studentHTML = template(data);
$("p").append(studentHTML);
Trying to make this work. I need to display FIRST_NAME and LAST_NAME values beetween to new TDs. The value are stored in an object of the data item. I can't seem to loop througt the child object.
Template example
<script id="row_tmpl" type="text/x-jsrender">
<tr id="{{>id}}">
<td class="textC">{{>id}}</td>
<td class="">{{>email}}</td>
{{for data}}
??????
{{/for}}
</tr>
</script>
Here is an example of the json object sent to the template ( actually, data.results is sent to the template )
{
"results":[
{
"id":"1",
"email":"aaaa#test.com",
"data":{
"1":{
"first_name":{
"value":"Name 1",
"public":"1",
"field":"1",
"mandatory":"1",
"possible_value":"",
"type":"text"
},
"last_name":{
"value":"Name 2",
"public":"1",
"field":"2",
"mandatory":"1",
"possible_value":"",
"type":"text"
}
}
}
},
{
"id":"2",
"email":"test2#test.com",
"data":{
"2":{
"first_name":{
"value":"Name 3",
"public":"0",
"field":"1",
"mandatory":"1",
"possible_value":"",
"type":"text"
},
"last_name":{
"value":"Name 4",
"public":"0",
"field":"2",
"mandatory":"1",
"possible_value":"",
"type":"text"
}
}
}
}
]
}
That's a poorly structured response. I should not need to know the id of data's parent to access its children. Also, data isn't an array.
<script id="row_tmpl" type="text/x-jsrender">
<tr id="{{>id}}">
<td class="textC">{{>id}}</td>
<td class="">{{>email}}</td>
<td class="">{{>data.{{:id}}.first_name.value}}</td>
<td class="">{{>data.{{:id}}.lastt_name.value}}</td>
</tr>
</script>