I want an Angular list showing all the instances of one object property from an array of objects, and nothing more – for example, only the countries.
$scope.testSites = [
{ "site": "Testsite1", "country": "Country1", "customer": "Customer1"},
{ "site": "Testsite2", "country": "Country2", "customer": "Customer2"}
];
$scope.chosenCategory = 1;
$scope.categoryNames = ["site", "country", "customer"];
$scope.aspect = $scope.categoryNames[$scope.chosenCategory];
However, I want to use the above variable 'aspect' for choosing which property to show in the list. Something like {{x.country}}, though it works, is therefore not sufficient. I've tried this, but it returns an empty list:
<table border="1" class="list-group-item list-group-item-success">
<tr>
<th>{{aspect | capitalize}}</th>
</tr>
<tr ng-repeat="x in testSites | orderBy:myOrderBy">
<td>
{{x.aspect}}
</td>
</tr>
</table>
Is there something I can do?
You can do via {{ x[aspect] }} - [] bracket notation. It evaluates the expressoin and uses the result to find the property.
You can find Demo here
Related
I am trying to repeat a child array of a multidimensional array with ng repeat in Angular.
My json object is this:
$scope.items = [{ "id":1,
"BasisA":"1",
"Basis":true,
"personSex":"m",
"isCollapsed":false,
"name":"Mark Polos",
"age":"1955",
"results":[{"1000":{"company_name":"***","model":"***","modelname":"***","pr":222,"rating":4.5,"priority":9,"matching":1},
"1001":{"company_name":"***","model":"***","modelname":"***","pr":228.7,"rating":5.7,"priority":7,"matching":2},
"1002":{"company_name":"***","model":"***","modelname":"***","pr":241.7,"rating":1.9,"priority":4,"matching":3}
}]
}]
Itried somthing like this:
... data-ng-repeat="item in items">
And then in the table of this child:
<tr data-ng-repeat="i in item | orderBy:'insItem.pr'">
It doesn't look like that results property is actually an "array." If that's just a typo in your example, then disregard. If not ... read on.
It looks like an array with a single item, and that Item is a set of properties which are, in turn, objects. In other words, you would reference the property "pr" for the result named "1000" by with code that looks like item.results[0]["1000"].pr NOT with code that looks the way your ng-repeat is expecting(item.results[0].pr).
Can you transform your items when you get them so that results is a true array?
OR - can you use a function inside of your controller that returns the array you are looking for?
View Code:
<... data-ng-repeat="result in resultsFromItem(item)" >
Controller Code:
$scope.resultsFromItem = function (item) {
if(item==undefined || item.results==undefined || item.results.length==0) {
return [];
}
var myResults = [];
for (var key in item.results[0]) {
if(item.results[0].hasOwnProperty(key)) {
myResults.push(item.results[0][key]);
}
}
return myResults;
}
You might even decide to hang that "transformed" results object off each item object (so you only have to go through the transform one time) if you wanted to.
You should access to the results field:
... data-ng-repeat="item in items">
<tr data-ng-repeat="i in item.results">
Since the nested array is in the results property of the main object.
I used three nested ng-repeat directives to get this rolling :-) The third ng-repeat uses ng-repeat="(key, value) in result" functionality to display all result object keys and values, which I got working with the help of this answer on how to iterate over keys and values in ng-repeat. The orderBy: part isn't yet working (if someone knows how to implement that then any help is welcomed).
<ul>
<li ng-repeat="item in items">
id: {{item.id}}, name: {{item.name}}, age: {{item.age}}, results:
<table>
<tr ng-repeat="result in item.results">
<td>
<table style="border: 1px solid black;">
<tr ng-repeat="(key, value) in result | orderBy: value.pr">
<td> {{key}} </td> <td> {{ value }} </td>
</tr>
</table>
</td>
</table>
</li>
</ul>
Plunker
In AngularJS I have a problem that a variable is assigned a value of another object.
I have ng-table and this work fine
<table ng-table="tableParams" data-ng-init="getMeasureUnits()" class="table" >
<tr ng-repeat="measUnit in measureUnits" ng-click="oneEntity(measUnit)">
<td data-title="'Id'" >{{measUnit.idUnit}}</td>
<td data-title="'Name'" >{{measUnit.name}}</td>
<td data-title="'abb'" >{{measUnit.abb}}</td>
</tr>
in Controller I have function oneEntity and I got one entity from table in function but can't be assigned to another entity that which I present it in another table.
$scope.measureUnitOne = {};
$scope.oneEntity = function(entity){
$scope.measureUnitOne = entity;
$location.path("/administration/edit/measureUnit.id");
};
After function I get fine location url I everything OK byt did't display the values in table :
...
<input type="text" class="form-control" id="mesaureUnitName" data-ng-model="measureUnitOne.name" placeholder="Name">
...
Object {name: "Litar", abb: "l", last_update: 1441538332000, id_user: 123, idUnit: 2}
$$hashKey: "object:46"
abb: "l"
idUnit: 4
id_user: 123
last_update: 1441538363000
name: "Litar"
proto: Object
In first case when i Write values , table show values , in second case, that is what I got after function and noting show ... Can someone telm me where is problem ??
I'm using Knockout to bind data to a table:
I have obj:
obj=[{id:"1",productName:"laptop",tag:[promotion,blackfriday]},{id:"2",productName:"Samsung galaxy note III",tag:[samsung,galaxy]}]
HTML:
<table data-bind="foreach:list" id="listProduct">
<tr>
<td data-bind="text:productName"></td>
<td data-bind="foreach:obj.tag">
<p data-bind="text:tag"></p>
</td>
</tr>
</table>
JavaScript (to bind data):
ko.applyBindings({ list: obj }, document.getElementById('listProduct'));
But it only displays the product name and does not bind "tag" obj; I want Knockout to bind data as:
Product Name Tag
1 Laptop promotion
blackfriday
2 Samsung galaxy note III samsung
galaxy
based on the code you gave, there are a couple simple things that will fix this for you:
productName is misspelled
the foreach:obj.tag should be foreach:tag
the text:tag should be text:$data (see the docs on this)
your tags in the data given are not strings - so it won't work if they aren't defined elsewhere
JS:
var obj = [{
id: "1",
productName: "laptop",
tag: ["promotion", "blackfriday"]
}, {
id: "2",
productName: "Samsung galaxy note III",
tag: ["samsung", "galaxy"]
}];
ko.applyBindings({ list: obj }, document.getElementById('listProduct'));
HTML:
<table id="listProduct">
<tr data-bind="foreach:list">
<td data-bind="text:productName">test</td>
<td data-bind="foreach:tag">
<p data-bind="text:$data">test</p>
</td>
</tr>
</table>
The implementation that are you using is too odd, and I think is not correct. For example I don't know why are you retrieving the listProduct element and sending as argument to ko.applyBidning, this is not how knockout works.
You also have mistakes using inside object in the foreach binding, check out documentation to see the correct usage. Even you have a misspelled in the HTML with the productName value.
You have syntax errors inside both tag arrays, the values are string so you need to add quotes to each element.
I will show a better and clean way to do it fixing the issues mentioned above:
JS
function VM(){ //declare your VM constructor.
this.list = ko.observableArray([
{id: '1', productName: 'laptop', tag: ['promotion', 'blackfriday']},
{id: '2', productName: 'Samsung galaxy note III', tag: ['samsung', 'galaxy']}
]); //Add and observable array an set your data. If you don't need that this array be an observable just use a normal JS array.
}
ko.applyBindings(new VM()); //apply binding
HTML
<table data-bind="foreach: list">
<tr>
<td data-bind="text: productName"></td>
<td data-bind="foreach: tag">
<p data-bind="text: $data"></p>
</td>
</tr>
</table>
Check out this fiddle to see it working.
How do you go about editing an array of objects bound to a table using ng-repeat ?
I have the following starting array.
var students = [{
"FName": "Tom",
"LName": "Wilcox"
}, {
"FName": "Kevin",
"LName": "Johnson"
}, {
"FName": "Annebelle",
"LName": "Smith"
}, {
"FName": "Kelly",
"LName": "Masters"
}, {
"FName": "Phillip",
"LName": "Smith"
}, ];
I then push two of the students onto a second array and add a new property called "Grade" like this:
var testTakers = [];
var s;
for (s = 0; s < students.length; s++) {
if (students[s].LName == "Smith") {
students[s].Grade = ""; // New Grade Property
testTakers.push(students[s]);
}
}
$scope.TestTakers = testTakers;
I add a new 'Grade' property to the two selected objects and bind to a table using ng-repeat. The Grade' property is bound to a textbox for editing.
<table class="table-striped">
<tbody>
<tr ng-repeat="student in TestTakers">
<td class="col-md-2">{{student.FName}}</td>
<td class="col-md-2">{{student.LName}}</td>
<td class="col-md-2">
<input type="text" size="2em" ng-bind="Grade" style="text-align:center" />
</td>
</tr>
</tbody>
When I enter the grades into the textboxes Angular is not persisting those values. My goal is to add grades to the two new student objects and then post them back up to the server.
A functioning Plunker sample is here. Thank you in advance for any assistance in helping me with this!
You need to use ng-model instead of ng-bind inorder to set up a 2-way binding with the user input on the textbox and the bound view model.
<input type="text" size="2em" ng-model="student.Grade" class="text-center" />
Plnkr
Side Note: Since you already have boostrap css loaded you can just use existing css rule text-center instead of inline style to specify style="text-align:center".
I have never used filters extensively in angularjs and I just saw a problem with one of my projects..
The filter that I apply to a table is filtering all columns except for the one that multiplies the values of two items in the repeater.
1. Is this meant to work this way?
2. Is there a way to filter the column that multiplies numbers or adds strings together?
Here is the plunker with a working (not working) example
http://plnkr.co/edit/pmCjQL39BWWowIAgj9hP?p=preview
I have a filter that I apply to ng-repeater...
<input type="text" ng-model="tableSearch">
And then in table..
<tr ng-repeat="items in tableData | filter:tableSearch">
<td> {{ items.qty }} </td>
<td> {{ items.price }} </td>
// hm.....
<td> {{ items.qty*items.price }} </td>
</tr>
Update
Thanks to guidance from #Chandermani below I resolved the issue writing a custom filter. Here is the updated plunk: http://plnkr.co/edit/pmCjQL39BWWowIAgj9hP?p=preview
$scope.tableFilter = function(item) {
for (key in item) {
var m = item[key].toString();
var s = (item.qty * item.price).toString();
if(
s.indexOf($scope.tableSearch) != -1 ||
m.indexOf($scope.tableSearch) != -1 ||
$scope.tableSearch == undefined
){
return true;
};
}
return false;
}
Then filter is used like this:
<tr ng-repeat="items in tableData | filter:tableFilter">
Filter work on model data, in your case this data
{
"id": 1,
"name": "Apples",
"price": 19.99,
"qty": 1
},
{
"id": 2,
"name": "Oranges",
"price": 29.99,
"qty": 1
},
The last column has been generated in html. You would have to write a custom filter function for supporting that or add the last column value also to your model.
For custom filter function you can do something like
$scope.tableFilter=function(item) {
//should return true for the item to show up.
}
see documentation for filter http://docs.angularjs.org/api/ng/filter/filter