Angularjs ng-repeat Array vs Object - angularjs

I am using ng-repeat to display data in a View coming from an endpoint in a form of atom feed. This endpoint returns JSON if Accept header is 'application/json', that JSON is created from XML on a server-side by an converter, unfortunately if there is one entry in the atom response then the entry in the JSON is not an array and ng-repeat does not work as expected. I had a project where I handled this manually by using a counter and then based on that counter and ng-show I either used ng-repeat or just displayed the single entry from the feed. How do I handle this correctly? Should I rework the incoming JSON on JS side? If yes could someone point me the right way of doing that.
<feed xmlns="http://www.w3.org/2005/Atom">
<id>/record</id>
<title type="text">Search feed</title>
<link href="/record" rel="self"/>
<link href="/record?page=2" rel="next"/>
<entry>
<id>recordid</id>
<link href="/record/id/recordid" rel="self"/>
<content type="recordcontenttype">
<record>...recordhere...</record>
</content>
</entry>
</feed>
{
"feed": {
"entry":
{
"content": {
...recordhere...
},
"type": "recordcontenttype"
},
"id": "recordid",
"link": {
"href": "/record/id/recordid",
"rel": "self"
}
},
-- if there would be more entries then entry would be an array [ { xx }, { xx } ] and ng-repeat would work --
"id": "/record",
"link": [
{
"href": "/record",
"rel": "self"
},
{
"href": "/record?page=2",
"rel": "next"
}
],
"title": {
"content": "Search feed",
"type": "text"
}
}
}

I'd suggest a simple filter, e.g.:
(function (app, ng) {
'use strict';
app.controller('AppCtrl', function AppCtrl() {
var vm = this;
vm.foo = { id: 1 };
vm.bar = [{ id: 2 }, { id: 3 }];
});
app.filter('ensureArray', function () {
return function (input) {
return ng.isArray(input) ? input : [input];
};
})
}(angular.module('app', []), angular));
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.1/angular.min.js"></script>
<div data-ng-app="app" data-ng-controller="AppCtrl as app">
<div data-ng-repeat="foo in app.foo|ensureArray">
{{ foo|json }}
</div>
<div data-ng-repeat="bar in app.bar|ensureArray">
{{ bar|json }}
</div>
</div>

Related

Json Object in ng-repeat

response object like
$scope.list= [
Object {
cid=74,
date="2016-08-25T00:00:00.000+0530",
optkey="key",
optvalue="{
value:{
'name':test,
'gender':male
}
}"
},
Object {
cid=75,
date="2016-08-25T00:00:00.000+0530",
optkey="key",
optvalue="{
value:{
'name':test2,
'gender':female
}
}"
}},
Object {
cid=77,
date="2016-08-26T00:00:00.000+0530",
optkey="key",
optvalue="{
value:{
'name':test1,
'gender':female
}
}"
}]
and in html page used ng-repeat
<div ng-repeat="item in list">
{{item.date}} -- works fine
</div>
here how to display json value in object optvalue, done some code like.
<div ng-repeat="item in list">
{{item.optvalue.value}} -- but it is undefined
</div>
but it is not working can any one give hint for this
Just because your optvalue is a String but not a object. It should be :
optvalue = {
value:{
'name':test1,
'gender':female
}
}
In JSON, an object should NOT be in the parenthese.
Try this working example, please check the object created.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.list=
[
{
cid:74, date:"2016-08-25T00:00:00.000+0530", optkey:"key", optvalue:{value:{'name':'test','gender':'male'}}
},
{
cid:75, date:"2016-08-25T00:00:00.000+0530", optkey:"key", optvalue:{value:{'name':'test','gender':'male'}}
},
{
cid:76, date:"2016-08-25T00:00:00.000+0530", optkey:"key", optvalue:{value:{'name':'test','gender':'male'}}
}
]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="item in list">
{{item.optvalue.value.name}}
</div>
</div>
The response JSON is not valid :
Strings should be wrapped in double quotes.
Expecting colon, not = in key value pairs.
Invalid characters found.
Invalid number.
Issue Capture :
Valid JSON :
[
{
"cid": 74,
"date": "2016-08-25T00:00:00.000+0530",
"optkey": "key",
"optvalue": {
"value": {
"name": "test",
"gender": "male"
}
}
},
{
"cid": 75,
"date": "2016-08-25T00:00:00.000+0530",
"optkey": "key",
"optvalue": {
"value": {
"name": "test2",
"gender": "female"
}
}
},
{
"cid": 77,
"date": "2016-08-26T00:00:00.000+0530",
"optkey": "key",
"optvalue": {
"value": {
"name": "test1",
"gender": "female"
}
}
}
]
In your case {{item.optvalue.value}} is giving undefined because optvalue is a string not an object.So, it should be an object.
"optvalue": {
"value": {
"name": "test1",
"gender": "female"
}
}
thanks for your answers,i have resolved it using--
angular.toJson and angular.fromJson
while send to server used
angular.toJson(stringOfJson)
and when got the response object the using
angular.fromJson(value)
and set to object field,it is working fine.
you need to change your code to this
<div ng-repeat="item in list">
{{item.optvalue.value.name}}
</div>

Reading nested json in Angularjs

I am newbie to AngularJS. I have JSON file which I have to fetch using angularjs!
JSON File
{
"records": [
{
"students": [
{
"id": 1,
"name": "Bill",
},
{
"id": 2,
"name": "Steve",
}
],
"exstudent": [
{
"id": 1,
"name": "Woz",
},
{
"id": 2,
"name": "Jonathan",
}
]
}
]
}
Controller part snippet -
$http.get('json/somedata.json').success(function (data){
$scope.name = data.records.student.name;
$scope.exname = data.records.exstudent.name;
});
}])
HTML
<div class="panel-body" ng-repeat = "browse in name">
{{browse.student.name}}
</div>
Which part I am doing wrong? I think the problem is with ng-repeat!
Need Help
You can't use data.records.students.name as students is an Array.
You can however store its data into your $scope and use it in the ng-repeat:
$http.get('json/config.json').success(function (data){
$scope.students = data.records.students;
$scope.exstudents = data.records.exstudent;
});
Then in your HTML use the ng-repeat like this:
<div class="panel-body" ng-repeat="student in students">
{{student.name}}
</div>

tags-input show a a element of an array

hi i have a JSON like this:
pages[
{
"id": "74682309",
"labels": [
{
"term": "test1",
"probability": 0.069
},
{
"term": "test2",
"probability": 0.037
}
]
}];
and using tags-input i want the tags to read only the term and show the term so i can show and update.
i have
<tags-input ng-model="se.labels"></tags-input>
the 'se' comes from ng-repeat="se in searchCtrl.pages
Based on the documentation (http://mbenford.github.io/ngTagsInput/documentation/api) you can change the keyProperty and displayProperty to make it use "term" instead of "text"
I've created a fiddle to demonstrate how you can obtain the data needed, considering that the provided JSON is a valid JSON. Your JSON is invalid.
var myApp = angular.module('myApp',['ngTagsInput']);
myApp.factory('data', function() {
var data = [
{
"id": "74682309",
"labels": [
{
"text": "test1",
"probability": 0.069
},
{
"text": "test2",
"probability": 0.037
}
]
}];
return data;
});
myApp.controller('MyCtrl', ['$scope', 'data', function($scope, data) {
var values = [];
data.map(function(elem) {
return elem.labels.forEach(function(el) {
values.push({
"text" : el.text
});
});
});
$scope.tags = values;
}]);
And the html part:
<div ng-controller="MyCtrl">
<div class="elem">
<tags-input ng-model="tags"></tags-input>
</div>
</div>
Here is the fiddle:
http://jsfiddle.net/HB7LU/16554/
Update:
You haven't included the angular ng-tags-input extension as a tag into your question. Please see my updated fiddle:
http://jsfiddle.net/HB7LU/16557/

How to bind Kendo grid to json data using angularjs

HI i am using kendo grid to bind data with json and angularjs
here is my code below.
this is the .cshtml page code below.
<div ng-app="Sample" ng-controller="SampleController">
<div>Products: {{products.length}}</div>
<div kendo-grid k-data-source="products" k-selectable="'row'"
k-pageable='{ "pageSize": 2, "refresh": true, "pageSizes": true }'
k-columns='[
{ "field": "EmployeeKey", "title": "EmployeeId"},
{ "field": "FirstName", "title": "First Name"},
{ "field": "LastName", "title": "Last Name"},
{ "field": "DepartmentName", "title": "Department Name" },
{ "field": "EmailAddress", "title": "Email Id" }
]'>
</div>
</div>
<script>
var app = angular.module('Sample', ['kendo.directives']);
app.controller('SampleController', function ($scope, $http) {
debugger;
$http.get('~/api/Employee/Employee_Read').success(function (thisdata) {
var myData = $.parseJSON(JSON.parse(thisdata));
$scope.myData = myData;
});
$scope.filterOptions = {
filterText: '',
useExternalFilter: true,
};
});
</script>
and in controller which name is EmployeeController i used json data like below:
public ActionResult Employee_Read ([DataSourceRequest] DataSourceRequest request )
{
return Json(employeeRepositary.Employees.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
This code is working fine with #HtmlKendo grid but for this i am not able to display data.
Where i am wrong??
Please help me out from here.
Use kendo.data.ObservableArray for this case
$http.get('~/api/Employee/Employee_Read').success(function (thisdata) {
var myData = $.parseJSON(JSON.parse(thisdata));
$scope.products= new kendo.data.ObservableArray(myData.Data);
});

ng-repeat + ng-bind Generates 120 loops when should be only 20. No idea why

Trying to create a dynamic svg icon generator to flesh out a grid of 5 days * 4 time periods per day with a built-on-the-fly svg.
Expected: 20 repeats
Result: 120 repeats, which has 20 svgs that repeat the contents 5 times
Why? No idea.
somecontroller.js:
var counter = 0;
$scope.iconGenerator = function ( i, parenti, tod ) {
counter++;
// console.log(counter);
//append svg contents
}`
index.html
<div class = "row">
<div class = "forecast-day col-md-fifth" ng-repeat = 'day in forecastData'>
<div class = "forecast-group" ng-repeat = "dayDetails in day.conditions">
<svg id = "{{myID($index, $parent.$index)}}"
ng-bind = "iconGenerator($index,$parent.$index, dayDetails)">
</svg>
</div>
</div>
</div>
data.json:
[
{
"ID" : 0,
"conditions": [
{
"key": "value"
},
{
"key": "value"
},
{
"key": "value"
},
{
"key": "value"
}
]
}
//array contains total: 5 objects like above
]
Edit:
I get it now. You are incrementing the value of a variable in the function you call in the ng-bind directive. This is never a good idea. I think that ng-bind must always refer to a variable or a 'getter' function that does not modify the state of the application.
To understand what I am trying to suggest, look again at the plunk http://plnkr.co/edit/eMams7nTe5qcxw2jC39i?p=preview. I added an input box with an ng-modelof x. Try modifying the input. Every time you change the input, angularjs has to reload the data in the entire document to check if anything changed. To do this, it must call the function iconGenerator repeatedly. In your case this function increments a value - and as a result the value increases every time you make a change.
You cannot rely on angular calling the iconGenerator function only once. So you need to change the code keeping that in consideration.
I tried to recreate your code here : http://plnkr.co/edit/eMams7nTe5qcxw2jC39i?p=preview and it seems to work fine. I think the problem is somewhere else (aside from the code you posted).
<head>
<script data-require="angular.js#1.3.0" data-semver="1.3.0" src="//code.angularjs.org/1.3.0/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script>
angular.module('app', [])
.controller('mainCtrl', function($scope) {
$scope.forecastData = [{
"ID": 0,
"conditions": [{
"key": "value"
}, {
"key": "value"
}, {
"key": "value"
}, {
"key": "value"
}]
}, {
"ID": 1,
"conditions": [{
"key": "value"
}, {
"key": "value"
}, {
"key": "value"
}, {
"key": "value"
}]
}, {
"ID": 2,
"conditions": [{
"key": "value"
}, {
"key": "value"
}, {
"key": "value"
}, {
"key": "value"
}]
}, {
"ID": 3,
"conditions": [{
"key": "value"
}, {
"key": "value"
}, {
"key": "value"
}, {
"key": "value"
}]
}, {
"ID": 4,
"conditions": [{
"key": "value"
}, {
"key": "value"
}, {
"key": "value"
}, {
"key": "value"
}]
}
];
var counter = 0;
$scope.iconGenerator = function(i, parenti, tod) {
counter++;
//append svg contents
};
});
</script>
</head>
<body ng-app="app">
<div ng-controller="mainCtrl">
<div ng-repeat="day in forecastData">
<div ng-repeat="dayDetails in day.conditions">
<svg id="{{myID($index, $parent.$index)}}" ng-bind="iconGenerator($index,$parent.$index, dayDetails)">
</svg>
{{$parent.$index}}-{{$index}}
</div>
</div>
</div>
</body>
</html>

Resources