I am using Angular.JS to retrieve data from an object array passed from the server. Each object has an ID, a name and a position identifier that is used to order the objects in a table.
However, orderBy does not work: here is an example output by showing the positions.
Here is the code of list.js :
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
});
and the JADE page:
doctype html
html
head
title Angular.js Test Page
link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css')
script(src='/javascripts/angular.min.js')
script(src='/javascripts/list.js')
body(ng-app='myApp', ng-controller='myCtrl' ng-init='list= #{JSON.stringify(list)}')
.col-lg-3
table.table.table-bordered
thead
tr
th User List
tfoot(ng-repeat="item in list | orderBy: 'position' track by item.position")
tr
td {{item.position}}
Here is the list that gets passed:
"list": [
{
"position": 5,
"name": "Item 1",
"id": 205690
},
{
"position": 9,
"name": "Item 2",
"id": 15540
},
{
"position": 12,
"name": "Item 3",
"id": 360640
},
{
"position": 27,
"name": "Item 4",
"id": 325470
},
{
"position": 7,
"name": "Item 5",
"id": 271670
},
{
"id": 72850,
"name": "Item 6",
"position": 9196
},
{
"id": 15080,
"name": "Item 7",
"position": 6863
},
{
"id": 242550,
"name": "Item 8",
"position": 6864
},
{
"id": 207490,
"name": "Item 9",
"position": 6865
},
{
"id": 15060,
"name": "Item 10",
"position": 6862
}
]
By all sources I checked, the ng-repeat syntax is correct.
Result is the same if I track by id, or remove track by; if I use OrderBy: '-position', position 9196 is put at the bottom (after '5').
Firefox console shows no warning or error at all!
Everything seems fine, so I am confused about what is going on. Can someone help?
Thanks.
Did you try to use tbody instead of tfoot ?
<div ng-app="myApp" ng-controller="myCtrl">
<table>
<thead>
<tr><td></td></tr>
</thead>
<tbody>
<tr ng-repeat="item in list | orderBy:'position' track by item.position">
<td>{{item.position}}</td></tr>
</tbody>
</table>
</div>
I did it in the JSFiddle and it works ...
maybe the problem is with your angular version.
my code works perfect when its on angularjs 1.2.1 and doesn't work on angularjs 1.0.3. see it for your self on this fiddle
<div ng-app>
<div ng-controller="ClickToEditCtrl">
<ul>
<li ng-repeat="item in test track by item.id">
{{item.name}}
</li>
</ul>
</div>
</div>
$scope.list = [
{
"position": 5,
"name": "Item 1",
"id": 205690
},
{
"position": 9,
"name": "Item 2",
"id": 15540
},
{
"position": 12,
"name": "Item 3",
"id": 360640
},
{
"position": 27,
"name": "Item 4",
"id": 325470
}
];
http://jsfiddle.net/Miqe/wqgkst7d/1/
Related
I have the following JSON data but would like to implement the HTML page such that it shows the parent as the header and all the children under the same parent under the content and then follow by the second parent as the header and all the children under the second parent under the content. How would I be able to do so? An example would be the following:
Sample 1
Product 1 - Test Product 1
Product 2 - Test Product 2
Sample 2
Product 1 - Test Product 1
"sampleList": [
{
"parent": "Sample 1",
"children": [
{
"product": "Product 1",
"name": "Test Product 1"
}
]
},
{
"parent": "Sample 1",
"children": [
{
"product": "Product 2",
"name": "Test Product 2"
}
]
},
{
"parent": "Sample 2",
"children": [
{
"product": "Product 1",
"name": "Test Product 1"
}
]
}
]
With Array.reduce() to perform group by parent and concatenate array.
Create a new array from result 1 with each object element has parent and children property.
let grouped = this.sampleList.reduce((groups, current) => {
groups[current.parent] = groups[current.parent] || [];
groups[current.parent].push(...current.children);
return groups;
}, Object.create(null));
this.groupedSampleList = Object.keys(grouped).map((key) => ({
parent: key,
children: grouped[key],
}));
If you use es2017, you can work with Object.entries() as:
this.groupedSampleList = Object.entries(grouped).map((value) => ({
parent: value[0],
children: value[1],
}));
<div *ngFor="let parent of groupedSampleList">
<strong>{{ parent.parent }}</strong>
<div *ngFor="let child of parent.children">
{{ child.product }} - {{ child.name }}
</div>
</div>
Demo on StackBlitz
The JSON data structure provided contains duplicate keys which is not ideal. Also, parents with the same value have children stored in separate locations. If the format could be improved such that each parent and child are separate items in the list, it can be easily performed iteratively using a ngFor, which allows you to iterate through data. Providing the JSON key will display the needed child elements. I have included an example below. https://angular.io/api/common/NgForOf
Reformatted Data:
sampleList":
[
{
"parent": "Sample 1",
"children": [
{
"product": "Product 1",
"name": "Test Product 1",
},
{
"product": "Product 1",
"name": "Test Product 1",
}],
},
{
"parent": "Sample 2",
"children": [
{
"product": "Product 1",
"name": "Test Product 1",
}]
}
]
<li *ngFor="let item of sampleList; index as I;">
<h3> {{item.parent}} </h3>
<li *ngFor="let item2 of sampleList[I].children;">
<div> {{item2.product}} - {{item2.name}}</div>
</li>
</li>
I am trying to solve a ng-repeat issue. I can see 2 ways to solve it 1. Using a filter to not repeat/display the object's property of category, which I am not sure how to do without using it's value or 2. If there is a way to say ng-repeat="i in items.drinks && items.sandwiches.
Is there no wildcard to say "category":"whatever"?
So in this case I am drilled down to where item = bottled-drinks and/or sandwiches. So when I do ng-repeat="i in item" category is lump in. I don't want it.
json -
food-items": {
"bottled-drinks": {
"category": "Bottled Drinks",
"drinks": {
"drink1": {
"title": "Drink Me 1",
"calories": "170"
},
"drink2": {
"title": "Drink Me 2",
"calories": "230"
},
"drink3": {
"title": "Drink Me 3",
"calories": "88"
}
}
},
"sandwiches": {
"category": "Sandwiches",
"sandwiches": {
"sandwich1": {
"title": "Sandwich Me 1",
"calories": "230"
},
"sandwich2": {
"title": "Sandwich Me 2",
"calories": "111"
},
"sandwich3": {
"title": "Sandwich Me 3",
"calories": "700"
}
}
}
Using your existing data structure, this would get you where you want to go.
NOTE: If you changed your data structure this would be much easier to implement. I'll show an example at the bottom.
Here is the fix for your current configuration.
<div ng-controller="MyCtrl">
<div ng-repeat="firstKey in firstKeys">
<div ng-repeat="secondKey in secondKeys">
{{ foodItems[firstKey][secondKey] }}
</div><br>
</div>
<br>
</div>
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.firstKeys = ["bottled-drinks", "sandwiches"];
$scope.secondKeys = ["drinks", "sandwiches"];
$scope.foodItems = {
"bottled-drinks": {
"category": "Bottled Drinks",
"drinks": {
"drink1": {
"title": "Drink Me 1",
"calories": "170"
},
"drink2": {
"title": "Drink Me 2",
"calories": "230"
},
"drink3": {
"title": "Drink Me 3",
"calories": "88"
}
}
},
"sandwiches": {
"category": "Sandwiches",
"sandwiches": {
"sandwich1": {
"title": "Sandwich Me 1",
"calories": "230"
},
"sandwich2": {
"title": "Sandwich Me 2",
"calories": "111"
},
"sandwich3": {
"title": "Sandwich Me 3",
"calories": "700"
}
}
}
}
}
This will result in a div with these values
{"drink1":{"title":"Drink Me 1","calories":"170"},"drink2":{"title":"Drink Me2","calories":"230"},"drink3":{"title":"Drink Me 3","calories":"88"}}
{"sandwich1":{"title":"Sandwich Me 1","calories":"230"},"sandwich2":{"title":"Sandwich Me 2","calories":"111"},"sandwich3":{"title":"Sandwich Me3","calories":"700"}}
Now you can use the keys you wish to use, but this is not that easy to do. If your data was instead structured like this...
$scope.edibles = [
{"category": "Bottled Drinks",
"types": [
{"title": "Drink Me 1",
"calories": "170"},
{"title": "Drink Me 2",
"calories": "230"},
{"title": "Drink Me 3",
"calories": "88"}
]},
{"category": "Sandwiches",
"types": [
{"title": "Sandwich Me 1",
"calories": "230"},
{"title": "Sandwich Me 2",
"calories": "111"},
{"title": "Sandwich Me 3",
"calories": "700"}
]}
]
<div ng-repeat="edible in edibles">
<div ng-repeat="foodType in edible.types">
Type: {{ foodType.title }}<br>
Calories: {{ foodType.calories }}
</div><br>
</div>
I only put this here because the comment-box is a pain sometimes:
Flat arrays are the easiest, most flexible and most efficient to work with:
$scope.foodItems = [ // Array (not object)
{
"id": "drink1",
"label": "Drink Me 1",
"calories": "170"
"category": "bottled-drinks",
},
{
"id": "sandwich1",
"label": "Sandwich Me 1",
"calories": "270"
"category": "sandwiches",
},
... (ALL ITEMS)
];
// Categories are a different resource, so better keep them in their own array.
// You'll thank me when you want move your stuff to some server-API.
$scope.categories = [
{ "id": "sandwiches", "category-label": "Sandwiches" },
{ "id": "bottled-drinks", "category-label": "Bottled Drinks" },
];
HTML
<div ng-repeat="category in categories">
<h2>{{ category.label }}<h2>
<div ng-repeat="item in foodItems" ng-if="item.category==category.id">
<h3>{{ item.label }}</h3>
<p>Calories: {{ item.calories }}</p>
<p>Description: {{ item.description }} (or whatever) </p>
</div>
</div>
You'll notice that you have to filter out some stuff (ng-if) but if you compare with SoEzPz's solution (which is not bad either) you'll have a much easier time when you want to show some custom list - for example show all items with less than 300 calories. (Since you don't need to concat arrays or whatnot.)
(There is a way to use angular $filters instead of ng-if... something like.... ng-repeat="item in foodItems | filter:{category:'sandwiches'}" (wild guess here!) But I'll leave it for you to research since I can't promise the syntax is correct from the top of my head.
Also, to be thorough, I would use a number based id (less messy), and use ng-repeat track by to gain some minor performance.
Not the answer I want, but I did an ng-if and in the controller I passed i then checked to see if i.title exist... if so display if not don't. There has to be a better way.
Good day everyone. I was hoping someone can help me with my Angular JS code. I have an image
which was populated based on this array of objects.
[
{
"groupName": "Group 1",
"devices": [
{
"deviceId": "1111",
"modelName": "Model 1",
"baseModelName": "base1",
"serialNumber": "ZZZZZZZZZZZ",
"ipAddress": "10.191.21.50",
"description": "Device 1"
},
{
"deviceId": "2222",
"modelName": "Model 2",
"baseModelName": "base2",
"serialNumber": "YYYYYYYY",
"ipAddress": "10.191.21.168",
"description": "Device 1"
}
]
},
{
"groupName": "Group 2",
"devices": [
{
"deviceId": "333",
"modelName": "Model 3",
"baseModelName": "base3",
"serialNumber": "XXXXXXXXXX",
"ipAddress": "10.191.21.124",
"description": "Device 1"
}
]
}
]
Would appreciate if anyone can help me in coding my angularjs javascript controller so that I can only check/uncheck the checkbox under the selected group(the radio button).
Thank You.
Use ng-disabled on the checkbox which can have the expression
"vm.selectedGroup !== 'Group 1'" or
"vm.selectedGroup !== group.name" assuming you have a ng-repeat which the element is called group
You can also have some logic to uncheck the checkboxes when the selectedGroup changes.
I’m using an external service to pull the events of an organisation (GetEvents). Example of what is returned:
{
"Result":"success",
"Key":"12345",
"Data":[
{"ID":"GFDCV34","lastChangedDate":"2015-12-03 11:14:27"},
{"ID":"IDJHE23","lastChangedDate":"2015-12-03 15:17:47"},
{"ID":"KDJBD34","lastChangedDate":"2015-12-03 05:25:11"}
]
}
Next, I can pull details of a certain event (GetEventDetails). The ID of the event is required as data parameter. I made a function getdetails(id); that returns the details.
For example, for getdetails('KDJBD34'), it gives me:
{
"Result":"success",
"Key":"52523",
"Data":[
{
"ID": "KDJBD34",
"name": "Name of event 3",
"date": "date of event 3",
"location": "location of event 3",
"lastChangedDate":"2015-12-03 05:25:11"
}
]
}
I want to construct an array containing all the events and their details, like this:
{
"Result": "success",
"Key": "12345",
"Data":[
{
"ID": "GFDCV34",
"name": "Name of event 1",
"date": "date of event 1",
"location": "location of event 1",
"lastChangedDate": "2015-12-03 11:14:27"
},
{
"ID": "IDJHE23",
"name": "Name of event 2",
"date": "date of event 2",
"location": "location of event 2",
"lastChangedDate": "2015-12-03 15:17:47"
},
{
"ID": "KDJBD34",
"name": "Name of event 3",
"date": "date of event 3",
"location": "location of event 3",
"lastChangedDate":"2015-12-03 05:25:11"
}
]
}
Anyone who can point me in the right direction?
You should operate through your first results and attach the new retrieved properties
var res = {
"Result": "success",
"Key": "12345",
"Data": [{
"ID": "GFDCV34",
"lastChangedDate": "2015-12-03 11:14:27"
}, {
"ID": "IDJHE23",
"lastChangedDate": "2015-12-03 15:17:47"
}, {
"ID": "KDJBD34",
"lastChangedDate": "2015-12-03 05:25:11"
}]
};
var tmp;
res.Data.map(function(val,i){
tmp = getdetails(val.ID);
Object.keys(tmp.Data[0]).map(function(v,j){
val[v] = tmp.Data[0][v];
});
});
Demo
Here is the Json message:
{"title": {"default":"hello 3", "position":[2,12,0]},
"description":{"default":"description hello 3", "position":[1,12,0]},
"option": [{"default":"1","position":[3,12,0]}, {"default":"2", "position":[0,12,0]}]
},
I am new to angularjs, I am trying to load the json message in ascending order according to the position first element by angularjs and print them in html. ("0" means load firstly, so on so far. )
Could someone help me on that? Thanks in advance!
Take a look at this
Working demo
html
<div ng-controller="MyCtrl">
<ul ng-repeat="value in data">Default:{{value.title.default}}
<li ng-repeat="pos1 in value.title.position|orderBy:orderByValue">{{pos1}}</li>Default:{{value.description.default}}
<li ng-repeat="pos2 in value.description.position|orderBy:orderByValue">{{pos2}}</li>
<li ng-repeat="val in value.option">Default:{{value.option[$index].default}}
<div ng-repeat="pos3 in val.position|orderBy:orderByValue">{{pos3}}</div>
</li>
</ul>
</div>
script
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function ($scope) {
$scope.orderByValue = function (value) {
return value;
};
$scope.data = [{
"title": {
"default": "hello 3",
"position": [2, 12, 0]
},
"description": {
"default": "description hello 3",
"position": [1, 12, 0]
},
"option": [{
"default": "1",
"position": [3, 12, 0]
}, {
"default": "2",
"position": [0, 12, 0]
}]
}];
});