Using Ng-table, I have tried to create one table view, that could be controlled from AngularJS parameters.
To control the header text, I need to put it in data-title or ng-data-title (Example: data-title="'Test'")
But, it always makes the table header empty.
Instead of filling it:
Code Snippet:
<td ng-repeat="v in tableSettings.data" data-title="v.name">
{{v.data?v.data(row):row[v.id]}}
</td>
Full Code:
<table ng-table="table" class="table" show-filter="{{tableSettings.filter}}">
<tr ng-repeat="row in $data">
<td ng-repeat="v in tableSettings.data" ng-click="tableSettings.click(row)" ng-attr-data-title="'{{v.name}}'"
ng-if="v.type!='switch'"
sortable="'{{sortable?sortable:v.id}}'">
{{v.data?v.data(row):row[v.id]}}
</td>
</tr>
</table
When I try to parse Angular into it, I just get errors: (press to see the errors)
"'{{v.name}}'" "{{v.name}}"
Is there a way to fix it, or even to parse it manualy from AngularJS?
Ok the problem is that the data-title attribute is meant to be used with static text (well known columns) such as data-title="'My first column'"
If what you need is dynamic columns you got to use the ng-table-dynamic directive.
For example:
<table ng-table-dynamic="tableParams with cols" show-filter="true" class="table table-bordered table-striped">
<tr ng-repeat="row in $data track by row.id">
<td ng-repeat="col in $columns">{{::row[col.field]}}</td>
</tr>
</table>
Take notice in the directive declaration uses a special syntax tablePrams with cols. Here the cols is a $scope variable that must follow the following schema for this to work properly.
$scope.cols = [
{ title: 'ID', field: 'id', filter: { id : 'text' }, show: true, sortable: 'id' },
{ title: 'Installation', field: 'installationAt' },
...
];
Title and field are mandatory whereas filter, show, sortable depend on your usage scenario.
You can play around with this code pen
Related
current I am working with a combination of datatables + angularjs. I'm following documentation here. https://l-lin.github.io/angular-datatables/archives/#!/gettingStarted
My table is rendering and getting populated with angularjs code. The issue I am coming across is I only want the photo text to appear only when it exist. When I inspect the element, ng-hide is always set. It'll appear fine if I remove ng-if.
Code
<table datatable="ng" class="contact-grid-table row-border" dt-options="vm.dtOptions2" dt-column-defs="vm.dtColumnDefs" dt-instance="dtInstanceCallback" id="tableId">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Photo</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="contact in vm.contacts">
<td>{{contact.firstName}}</td>
<td>{{contact.lastName}}</td>
<td><span ng-if="contact.photo">{{contact.photo}}</span></td>
</tr>
</tbody>
</table>
I also tried the suggestion here ng-show not working in datatables columns but my table will no longer load. Page just freezes.
May I ask if there's any suggestions on how to get ng-if/show to work with datatables.
vm.dtOptions2 = DTOptionsBuilder.newOptions()
.withOption('createdRow', function (row, data, dataIndex) {
// Recompiling so we can bind Angular directive to the DT
$compile(angular.element(row).contents())($scope);
})
.withOption('headerCallback', function (header) {
if (!vm.headerCompiled) {
// Use this headerCompiled field to only compile header once
vm.headerCompiled = true;
$compile(angular.element(header).contents())($scope);
}
})
.withPaginationType('full_numbers').withOption('responsive', true)
.withColReorder()
.withColReorderOrder([0,1, 2,3])
.withScroller()
.withOption('bFilter', false) // for search box
.withOption('bInfo', false) // for showing counts at the bottom
.withOption('deferRender', true)
.withOption('scrollY', 200)
// Set order
// Fix last right column
.withDisplayLength(2)
.withFixedHeader({
bottom: false
});
I have a table set up using the smart-table plug in for AngularJS. Everything appears to work nicely. Rather than having the user click on the table header to trigger a sort, I'd like to programmatically trigger sorting from my Angular controller. I do not see a way of doing this in the documentation here:
http://lorenzofox3.github.io/smart-table-website/
Am I overlooking something?
Found this on JSFiddle, might help you: http://jsfiddle.net/vojtajina/js64b/14/
<script type="text/javascript" ng:autobind
src="http://code.angularjs.org/0.10.5/angular-0.10.5.js"></script>
<table ng:controller="SortableTableCtrl">
<thead>
<tr>
<th ng:repeat="(i,th) in head" ng:class="selectedCls(i)" ng:click="changeSorting(i)">{{th}}</th>
</tr>
</thead>
<tbody>
<tr ng:repeat="row in body.$orderBy(sort.column, sort.descending)">
<td>{{row.a}}</td>
<td>{{row.b}}</td>
<td>{{row.c}}</td>
</tr>
</tbody>
</table>
A quick hack i found on how to do this is by setting the table header st-sort property and then triggering a click() on that element
<tr>
<th id="myelement" st-sort="date" st-sort-default="reverse">Date</th>
...
</tr>
Then later:
setTimeout(function() {
document.getElementById('myelement').click()
},
0);
Here is the 'angular' way to do this. Write a directive. This directive will have access to the smart table controller. It will be able to call the controller's sort by function. We will name the new directive stSortBy.
The below HTML includes the standard smart table syntatic sugar. The only new attribute directive here is st-sort-by. That's where the magic will happen. It's bound to a scoped variable sortByColumn. This is a string value of the column to sort
<table st-sort-by="{{sortByColumn"}}" st-table="displayedCollection" st-safe-src="rowCollection">
<thead>
<tr>
<th st-sort="column1">Person</th>
<th st-sort="column2">Person</th>
</tr>
</thead>
</table>
<button ng-click="toggleSort()">Toggle sort columns!</button>
Here is the stSortBy directive that hooks into the st table controller
app.directive('stSortBy', function() {
return {
require: 'stTable',
link: function (scope, element, attr, ctrl) {
attr.$observe('stSortBy', function (newValue) {
if(newValue) {
// ctrl is the smart table controller
// the second parameter is for the sort order
ctrl.sortBy(newValue, true);
}
});
}
};
});
Here is the controller. The controller sets the sort by in it's scope
app.controller("MyTableWrapperCtrl", ["$scope", function($scope) {
$scope.sortByColumn = 'column2';
$scope.toggleSort = function() {
$scope.sortByColumn = $scope.sortByColumn === 'column2' ? 'column1' : 'column2';
// The time out is here to guarantee the attribute selector in the directive
// fires. This is useful is you do a programmatic sort and then the user sorts
// and you want to programmatically sort back to the same column. This forces a sort, even if you are sorting the same column twice.
$timeout(function(){
$scope.sortByColumn = undefined;
}, 0);
};
}]);
I have this data:
{
"order":[
{
"id":1,
"table":1,
"foods":"{'foods':[{'id':2, 'name':'Nasi Minyak', 'qty':1}]}",
"drinks":"{'drinks':[{'id':1,'name':'Teh O Ais','qty':1}]}",
"waiter":"ali",
"foods_status":0,
"drinks_status":0,
"created_at":"2015-07-12T00:30:52.637Z",
"updated_at":"2015-07-12T00:30:52.637Z"
},
{
"id":2,
"table":2,
"foods":"{'foods':[{'id':2, 'name':'Nasi Goreng', 'qty':1}]}",
"drinks":"{'drinks':[{'id':1,'name':'Milo Ais','qty':1}]}",
"waiter":"abu",
"foods_status":0,
"drinks_status":0,
"created_at":"2015-07-12T00:51:43.552Z",
"updated_at":"2015-07-12T00:51:43.552Z"
}
]
}
I try to grab all foods name inside table like this:
<table class="table-bordered table table-striped">
<thead>
<tr>
<td>#</td>
<td>Name</td>
<td>Action</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="order in orders">
<td>{{order.id}}</td>
<td>{{order.foods.name}}</td>
<td>
<button class="btn btn-danger" ng-click="">Delete</button>
</td>
</tr>
</tbody>
</table>
And this is my $http.get to get the data:
$http.get("../api/orders")
.success(function(data) {
var order = data.order;
$scope.orders = order;
});
I managed to bind the id but I could't bind the name inside the foods array.
How to get the name inside the foods array of this data?
Plunker:
http://plnkr.co/edit/2oiOc06cZph4en8DJ18n
You need another ng-reapeat. Something like this:
<tr ng-repeat="order in orders">
<td>{{order.id}}</td>
<td>
<span ng-repeat="item in order.foods.foods">{{item.name}}/</span>
</td>
<td>
<button class="btn btn-danger" ng-click="">Delete</button>
</td>
</tr>
Another consideration is about the format of your JSON. this line:
"foods":"{'foods':[{'id':2, 'name':'Nasi Minyak', 'qty':1}]}"
the way it is, "foods" is holding a String, and not a Object. To make the ng-reapeat work, you will need to force JSON from string using
JSON.parse(jsonString);
or change your JSON to:
"foods":{"foods":[{"id":2, "name":"Nasi Minyak", "qty":1}]}
Side note, why repeat the keys "foods" and "drinks"? Doesn't seem logic to me. Change your data structure to:
"order":[
{
"id":1,
"table":1,
"foods":[{"id":1, "name":"Nasi Kerabu", "qty":1},{"id":2, "name":"Nasi Minyak", "qty":1}],
"drinks":[{"id":1,"name":"Sirap Ais","qty":1},{"id":2, "name":"Milo Ais", "qty":1}],
"waiter":"ali",
"foods_status":0,
"drinks_status":0,
"created_at":"2015-07-12T00:30:52.637Z",
"updated_at":"2015-07-12T03:30:35.684Z"
},
...
]
and use:
<td> <span ng-repeat="item in order.foods">{{item.name}}</span> </td>
Here is a plunker with these modifications:
http://plnkr.co/edit/UVvCVzh4hbsEwolyWpDs?p=preview
Here is a plunker that works http://plnkr.co/edit/snE9Em0tCKh0nUHIlTFn?p=preview.
Consider modifying your JSON file. Use double quotation marks instead of single quotation marks.
In your modified JSON file in your new plunker remove double quotations marks here "[{'id':1,
I have made some changes in your data and it fix the issue you are facing.
Here is plunker link
`http://plnkr.co/edit/nxBGMMyuNIzUOvQAu7YY?p=preview`
Each order would be an object like this:
{
"id":2,
"table":2,
"foods":"{'foods':[{'id':2, 'name':'Nasi Goreng', 'qty':1}]}",
"drinks":"{'drinks':[{'id':1,'name':'Milo Ais','qty':1}]}",
"waiter":"abu",
"foods_status":0,
"drinks_status":0,
"created_at":"2015-07-12T00:51:43.552Z",
"updated_at":"2015-07-12T00:51:43.552Z"
}
Note that foods points to an object, whose only key 'foods' points to an array... whose first component should be an object. However, if you read more closely:
"foods":"{'foods':[{'id':2, 'name':'Nasi Goreng', 'qty':1}]}",
Notice the double quotes surrounding foods's value? They mean that it points to a String instead of an object.
First, you need to delete the double quotes surrounding the values of both foods and drinks:
"foods":{'foods':[{'id':2, 'name':'Nasi Goreng', 'qty':1}]},
"drinks":{'drinks':[{'id':1,'name':'Milo Ais','qty':1}]},
And then replace all the single quotes with double ones, to make the object comply with the JSON object definition:
"foods":{"foods":[{"id":2, "name":"Nasi Goreng", "qty":1}]},
"drinks":{"drinks":[{"id":1,"name":"Milo Ais","qty":1}]},
Now, to get 'name', you need to access order.foods.foods[0].name instead of order.foods.name.
I have a table using angularjs where I want to loop through an array to print specific headers from a json object. The header prints out fine, but the problem comes when I try to use a variable from my nested ng-repeat as a json selector. If you replace the inner ng-repeat with the commented section below it, it will work.
Table:
<table>
<thead>
<th ng-repeat="column in tableHeader">{{column}} <a ng-click="sort_by(column);"><i class="glyphicon glyphicon-sort"></i></a></th>
</thead>
<tbody>
<tr ng-repeat="data in filtered>
<td ng-repeat="column2 in tableHeader">{{data.column2}}</td>
<!-- <td>{{data.Environment}}</td>
<td>{{data.HostIP}}</td>
<td>{{data.ServiceName}}</td>
<td>{{data.Status}}</td>
<td>{{data.StartTime}}</td>
<td>{{data.Capacity}}</td>
<td>{{data.Txn}}</td>
<td>{{data.Errors}}</td>
<td>{{data.Build}}</td>
<td>{{data.Project}}</td>
<td>{{data.Author}}</td>
<td>{{data.ModifyDate}}</td>
<td>{{data.Port}}</td>
<td>{{data.BasePath}}</td> -->
</tr>
</tbody>
</table>
Array located in controller:
$scope.tableHeader = ['Environment', 'HostIP', 'Status', 'ServiceName', 'StartTime', 'Capacity', 'Txn', 'Errors', 'Build', 'Project', 'Author', 'ModifyDate', 'Port', 'BasePath'];
I think you're looking for {{data[column2]}}. Since column2 is just the string value of the property you want, treat data like an associative array in this case to get the property you're trying to display.
column2 was created by the ng-repeat and is what you want. Note {{column2}}:
<td ng-repeat="column2 in tableHeader">{{column2}}</td>
I'm using a table with the jquery dataTable plugin.
When I use the function fnAddData it works, except when the table is empty. Then, I get this error :
Cannot read property 'className' of undefined
This is how I add my data:
$("#table-1").dataTable().fnAddData([
data[0],
data[1],
data[2],
data[3],
data[4],
data[5],
data[6],
data[7],
data[8],
]);
And I have the same problem with fnDeleteRow with this error message:
Cannot read property 'nTr' of undefined
Here's how I use fnDeleteRow, I have no trouble when the table is not empty...
$("#table-1").dataTable().fnDeleteRow(tr)
where tr is a selector.
Am I missing something?
Here's my HTML tab with one last row :
<table id="table-1" class="table table-hover table-nomargin table-colored-header dataTable" aria-describedby="table-1_info">
<thead>
<tr role="row">
<th class="sorting" role="columnheader" tabindex="0" aria-controls="table-1" rowspan="1" colspan="1">Pays</th>
</tr>
</thead>
<tbody role="alert" aria-live="polite" aria-relevant="all">
<tr class="odd">
<td class=" sorting_1">
<div id="address23name">test</div>
</td></tr></tbody></table>
And here's my JS
$("#deleteAddressButton").click(function(){
var id = $("#deleteAddressId").val();
$.post("/Contacts/deleteAddress",
{data: id}, function(data) {
var id = $.parseJSON(data);
var tr = $("tr:has(td:has(div:contains(\"address\" + id + \"Name\")))");
$("#table-1").dataTable().fnDeleteRow(tr)
});
})
jQuery doesn't allow DataTables to access the data in the way that it prefers. In order to give it the node that it wants, you will probably need to apply [0] or .get(0) to the end of your jQuery object. That is actually what jQuery returns -- an object -- and normally exactly what you would be comfortable working with.
DataTables wants a node.
Here are some links that show the developer giving hints about how to access the data in different circumstances -- but with the same error in the 2nd link:
here
and
here
The moral of the story is that if DataTables is expecting a table "node", you need to do some extra footwork to remove the extra jQuery container that it is placed within.
Your code would, therefore, look like this and I believe should handle your error condition. Otherwise, be sure to search for your error and function name on DataTables.net. That forum is very active and helpful.
var tr = $("tr:has(td:has(div:contains(\"address\" + id + \"Name\")))");
$("#table-1").dataTable().fnDeleteRow(tr[0])
or
var tr = $("tr:has(td:has(div:contains(\"address\" + id + \"Name\")))");
$("#table-1").dataTable().fnDeleteRow(tr.get(0))
or of course, add it to the end of your lengthy $("tr:has...) statement.
Option 2:
Just hide the row you want to delete
If these ideas don't help, you may find allan's answers here insightful.
Here's a simple jsfiddle, which allows you to add a row to an empty table:
http://jsfiddle.net/7UZGM/
So what's different about your table? When you say "empty", does it still have a thead/tr/th section and an empty tbody section? These are required for datatables to work properly.
$('#dt').dataTable();
$('#btn').on('click',function() { addData(); });
function addData()
{
$("#dt").dataTable().fnAddData([
"col 1", "col 2", "col 3"]);
}