Creating table with unknown headers with angular.js - javascript

I have a .json with unknown attributes and want to graph them. In my controller I have already extracted the headers and saved them as table_headers, from the doubleObjects Object. The data looks like this:
$scope.items = {[
...,
{doubleObjects: [{...}, {...}, ...]},
...,
]};
This is what I'm trying to output:
<table style="width:100%" border="1px solid black">
<tr>
<th ng-repeat="y in table_headers">{{y}}</th>
</tr>
<tr ng-repeat="x in items.doubleObjects">
<td ng-repeat="y in table_headers">{{x.y}}</td>
</tr>
</table>
So I would like the entire doubleObjects object to be tabulated. It wont let me do:
{{x.y}}
If I do:
{{x.measurement}}
or another attribute that is in doubleObjects then its all fine. But I cant ensure that the "measurement" attribute will be there. (For my test data it is.)
Thoughts and suggestions are most welcome.

You should not use x and y that way {{x.y}} use it this way {{x[y]}} or like the other way shown in this jsfiddle which shows both possibilities. I stated both possibilities, as I didn't really understood what you are looking for and I'm not allowed to comment your post.
<tr ng-repeat="x in items.doubleObjects">
<td ng-repeat="y in table_headers">{{x.measurement}}.{{y}}</td>
<td ng-repeat="y in table_headers">{{x[y]}}</td>
</tr>

Related

Sort data in Single column on the table based on the Heading in Angular

What I am working on is to perform sort operation in a table on a single or multiple columns. Let's assume that we have a table like this.
On clicking on Heading 1 only the Data 1 and Data 2 should be sorted when clicking on the Heading 2 the Data 3 and Data 4 need to be sorted.
Have implemented simple sort for the table in Angular, but cannot get an idea how to implement this one with two sets of data in a single column.
Even tried separate tables since the order by in Angular is based on the key in the array, both(Data 1,2,3 & 4) are getting updated when clicking on the Heading 1.
ng-repeat is used to form the table
Can anyone point me in the right direction(on Angular 1.x)?
Sample Fiddle http://jsfiddle.net/ANEA6/13/
The problem is that you're using the same variable to handle the reverse!
<div ng-controller="MyCtrl">
<table class="table">
<tr class="heading">
<td ng-click="reverse1=!reverse1;predicate1='id'">id</td>
</tr>
<tr ng-repeat="user in users | orderBy:predicate1:reverse1">
<td>{{user.id}}</td>
</tr>
<tr class="heading">
<td ng-click="reverse2=!reverse2;predicate2='id'">id</td>
</tr>
<tr ng-repeat="user in users | orderBy:predicate2:reverse2">
<td>{{user.id}}</td>
</tr>
</table>
</div>
You can check this working fiddle ==> http://jsfiddle.net/ANEA6/17/
Why don't you create a separate scope variable for each <tr> where there is id inside the <td> like this
<div ng-controller="MyCtrl">
<table class="table">
<tr><td ng-click="reverse1=!reverse1;predicate1='id'">id</td></tr>
<tr ng-repeat="user in users | orderBy:predicate1:reverse1">
<td>{{user.id}}</td>
</tr>
<tr><td ng-click="reverse2=!reverse2;predicate2='id'">id</td></tr>
<tr ng-repeat="user in users | orderBy:predicate2:reverse2">
<td>{{user.id}}</td>
</tr>
</table>
</div>
Controller
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.users = [
{id:1},
{id:2}
]
}
This should work in your case as i do not see the <td> with id being generated dynamically. It is hard coded to two rows with id. The other <tr> following the id <tr> are dynamically generated using ng-repeat so this should be fine.
For your simplicity here is the working link to JSFIDDLE

split a string (ng-model) created inside ng-repeat directive

I start to play with angularjs, and having this data model :
friends = [
{name:'John**amine**allo'},
{name:'Mary**aaa**mmm'},
{name:'Mike**bb**kkk'}
]
I would like to split each name by '**' to create a table of names.
I don't know if there is more straightforward way to do this ( maybe using some filter in angular-filter module) but here what I have so far tried:
<table id="searchObjResults">
<tr><th>Name</th></tr>
<tr ng-repeat="x in friends">
<td ng-repeat="y in x.split('**')">
{{y}}
</td>
</tr>
thanks in advance for any help.
You need to split name property if the x elements:
<td ng-repeat="y in x.name.split('**')">{{y}}</td>
However this is probably not very good idea what you are trying to do. First of all, you need to take care of proper table structure (correct header colspan values). Secondary, it's better to render already processed data structure, rather then converting values inside templates. It just makes it overcomplicated, not to mention makes watch expression slower.
Demo: http://plnkr.co/edit/5PXTW1gjpKwg7e3S6hRM?p=preview
You can use a custom filter to specify the separator:
<table id="searchObjResults">
<tr><th>Name</th></tr>
<tr ng-repeat="x in friends">
<td ng-repeat="y in x.name | mysplit:'**'">
{{y}}
</td>
</tr>
</table>
JS:
app.filter('mysplit', function() {
return function(data, sep) {
return data.split(sep);
}
});
Plunker

AngularJS data binding within another data binding

I just stepped into the AngularJS world, and need a solution for the application I am working on.
So here is the definition of the module.
var samplesApp = angular.module('samples', []);
samplesApp.controller('samplesController', function ($scope) {
var jsonObj=
[
{"ACTION":"UPDATE","ID":"22","ROUTE":"0015"},
{"ACTION":"DELETE","ID":"20","ROUTE":"0015"},
{"ACTION":"UPDATE","ID":"19","ROUTE":"0015"}
]
$scope.records = jsonObj;
var columnNames = [];
for (var key in jsonObj[0]) {
columnNames.push(key);
}
$scope.columnNames = columnNames;
});
The $scope JSON object is a part of the output of the real data that comes from database. and I need to put these data into a table dynamically
The html is like
<table>
<thead>
<th data-ng-repeat="column in columnNames">{{column}}</th>
</thead>
<tr data-ng-repeat="record in records">
<td data-ng-repeat="column in columnNames">{{ record.{{ column }} }}</td>
</tr>
</table>
Because I have no idea what the column name is, so I made a process to get all the column names and push them into $scope.columnNames. and then bind it to the table header. There is no problem for this part. The issue is I don't know how to get the value coresponse to the specific column. I was trying to do it like this:
<td data-ng-repeat="column in columnNames">{{ record.{{ column }} }}</td>
But apparently it is not working.
Can someone give me some advice? really appreciate it.
Try using brackets, like this:
<tr data-ng-repeat="record in AllRecords">
<td data-ng-repeat="column in columnNames">{{ record[column] }}</td>
</tr>
The expressions inside {{ }} (moustaches?) are evaluated pretty narrowly to how regular javascript is evaluated.
Accessing with the record[column] operator is OK, but
you could try this other alternative. In this example, the semantics
of the code is a bit better, and you have less coupling (your rows just
depend on the data, not the variable used in the header):
<table>
<tr>
<th data-ng-repeat="column in columnNames">{{column}}</th>
</tr>
<tr data-ng-repeat="record in records">
<td data-ng-repeat="(key,value) in record">{{value}}</td>
</tr>
</table>
Here's the working example with your data: http://plnkr.co/edit/CskLQ2ZZlYIURdNPXiZt?p=preview
Here's the Angular docs for the ngRepeat directive (look for "key, value")

Ng-repeat unexpected multiple repeat

I have an object that looks like this:
So basically I don't know the length of the object and I'm using the following code to render the result:
<table style="width: 100%" border="0" cellpadding="0" cellspacing="0">
<tr ng-repeat-start="(key, item) in items() track by key" ng-if="item.primary"></tr>
<td first someprop="2">first</td>
<tr ng-repeat-end ng-if="!item.primary">
<td>[NOT] first</tr>
</tr>
</table>
I want the first element in the table(it's also highlighted) to always be the object with the primary=true property.
Expected result with the object represented above:
Current result:
If I add a third element to the object, I'm getting:
FIDDLE: http://jsfiddle.net/UuzZT/
You have a simple semantic error in your HTML, specifically the ng-repeat-start element does not wrap the <td> so the <td> shows up each time even though the ng-if is there. Corrected here:
http://jsfiddle.net/UuzZT/1/
However, there are other problems stemming from the fact that you are trying to iterate over an object; objects do not have ordinal properties.
Your first table row does not include the table data (td outside tr)
Change your code to this:
<table style="width: 100%" border="0" cellpadding="0" cellspacing="0">
<tr ng-repeat-start="(key, item) in items() track by key" ng-if="item.primary">
<td first someprop="2">first</td>
</tr>
<tr ng-repeat-end ng-if="!item.primary">
<td>[NOT] first</tr>
</tr>

Adding Operations to Knockout Mapping Object

I am struggling with adding operations to my Knockout Mapping object.
Here is where I am at right now - and I am attempting to follow the Knockout: Mapping API information.
This is the HTML first:
+ Add Contact
<div id="ContactList">
<table>
<thead>
<tr>
<th>ID</th><th>Name</th><th></th>
</tr>
</thead>
<tbody data-bind="foreach: $root">
<tr>
<td data-bind="text: ContactID"></td>
<td data-bind="text: DisplayName"></td>
<td></td>
</tr>
</tbody>
</table>
</div>
And this is my first attempt at wiring up Knockout:
var baseModel = {
addContact: function() {
alert('Woo!');
}
};
contacts = ko.mapping.fromJS('[{"ContactID":6,"DisplayName":"Doe, John"},{"ContactID":7,"DisplayName":"Rogers, Mister"}]', { }, baseModel);
ko.applyBindings(contacts);
Now, if I remove the additional arguments ({} and baseModel) from the ko.mapping.fromJS, all my data is displayed in the table correctly. However (and as to be expected), I get a binding error with the "Add Contact" link. If I add baseModel back in, clicking the "Add Contact" link works, but no data displays. I get no errors one way or another, so I'm a bit stumped on what's going on there.
I'm new to KO, so I feel like I'm missing something pretty simple. I've searched across StackOverflow, but, at this point, I'm just plugging code in to see what works and not actually understanding what is happening here. Can someone provide some additional explanation and point me in the right direction? Thanks.
You're using ko.mapping.fromJS but you're passing a string, not an object/array. Either use fromJSON or pass in a real array.
Also, you should applyBindings on baseModel, and contacts should be a field of the VM. Then you can use foreach: contacts instead of your weird foreach: $root.
See fiddle with those changes: http://jsfiddle.net/antishok/kR4jc/3/
EDIT - Updating your answer with your code so the question can stand on its own.
JavaScript
var baseModel = {
addContact: function() {
alert('Woo!');
}
};
baseModel.contacts = ko.mapping.fromJSON('[{"ContactID":6,"DisplayName":"Doe, John"},{"ContactID":7,"DisplayName":"Rogers, Mister"}]');
ko.applyBindings(baseModel);​
HTML
+ Add Contact
<div id="ContactList">
<table>
<thead>
<tr>
<th>ID</th><th>Name</th><th></th>
</tr>
</thead>
<tbody data-bind="foreach: contacts">
<tr>
<td data-bind="text: ContactID"></td>
<td data-bind="text: DisplayName"></td>
<td></td>
</tr>
</tbody>
</table>
</div>​

Categories

Resources