Angular nested Data Tables with dynamic headers issue - angularjs

I am using Angular DataTables in my application and trying to create nested datatables with dynamic headers.
Here is my Html code.
<table datatable="ng" class="table table-striped table-bordered table-hover" dt-instance="dtInstance2" id="dtInvoicingData2" dt-options="dtOptions2" dt-column-defs="dtColumnDefs2">
<thead>
<tr>
<th ng-repeat="col in dtColumnDefs2">{{col.aTargets[0].sTitle | translate}} </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(index,client) in lstInvoiceDetail" class="clickableRow" style="cursor: pointer;" title="Click to toggle collapse/expand day summaries for this store.">
<td ng-repeat="col in headerList2" ng-switch="col">
<span ng-switch-when="lstDetail"> <button type="button" ng-click="btnViewDetails_Click(index)" class="btn btn-sm btn-info">+</button></span>
<span ng-switch-default>{{ client[col] }}</span>
</td>
</tr>
<tr ng-show="showViewDetail">
<div class="span12 pull-right" ng-show="showViewDetail">
<table datatable="ng" class="table table-striped table-bordered table-hover" dt-instance="dtInstance3" id="dtInvoicingData3" dt-options="dtOptions3" dt-column-defs="dtColumnDefs3">
<thead>
<tr>
<th ng-repeat="col3 in dtColumnDefs3">{{col3.aTargets[0].sTitle | translate}} </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(index,client) in lstInvoiceDetail" class="clickableRow" style="cursor: pointer;" title="Click to toggle collapse/expand day summaries for this store.">
<td ng-repeat="col3 in headerList3" ng-switch="col">
<span ng-switch-when="lstDetail"> <button type="button" ng-click="btnViewDetails_Click(index)" class="btn btn-sm btn-info">+</button></span>
<span ng-switch-default>{{ client[col3] }}</span>
</td>
</tr>
</tbody>
</table>
</div>
</tr>
</tbody>
</table>
Here is javascript Code
function makeDetailTable(data) {
var header = data[0],
dtColumns = [];
$scope.headerList2 = [];
var i = 0;
var key = "";
//create columns based on first row in Parent Datatable
for (var key in header) {
dtColumns.push(DTColumnDefBuilder.newColumnDef(i).withTitle(key));
$scope.headerList2.push(key);
i = i + 1;
}
$scope.dtColumnDefs2 = dtColumns;
$scope.dtOptions2 = DTOptionsBuilder.newOptions()
.withPaginationType('full_numbers')
.withButtons([
'excel',
{
text: 'Reset',
action: function (e, dt, node, config) {
$("#dtInvoicingData2").DataTable().search("").draw();
}
}
]);
}
$scope.btnViewDetails_Click = function (rowIndex) {
var detailList = $scope.lstInvoiceDetail[rowIndex]['lstDetail'];
var header3 = detailList[0],
dtColumns3 = [];
$scope.headerList3 = [];
var i = 0;
var key = "";
//create columns based on first row in child datatable
for (var key in header3) {
dtColumns3.push(DTColumnDefBuilder.newColumnDef(i).withTitle(key));
$scope.headerList3.push(key);
i = i + 1;
}
$scope.dtColumnDefs3 = dtColumns3;
$scope.dtInstance2 = null;
$scope.dtOptions3 = DTOptionsBuilder.newOptions()
.withPaginationType('full_numbers')
.withButtons([
'excel',
{
text: 'Reset',
action: function (e, dt, node, config) {
$("#dtInvoicingData3").DataTable().search("").draw();
}
}
]);
$scope.showViewDetail = true;
when I try to add child datatable it doesn't work and show console error
TypeError: Cannot set property '_DT_CellIndex' of undefined
I did search on this error but i have not find proper solution
Here is a little info related to this error
it says the problem is
Basically this issue came out because of miss matching count of th to td. be sure for number of th matches to td. hope this will help you.
Update:
Now i have trying this.
<table datatable="ng" class="table table-striped table-bordered table-hover" dt-instance="dtInstance2" id="dtInvoicingData2" dt-options="dtOptions2" dt-column-defs="dtColumnDefs2">
<thead>
<tr>
<th ng-repeat="col in dtColumnDefs2">{{col.aTargets[0].sTitle | translate}} </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(index,client) in lstInvoiceDetail" class="clickableRow" style="cursor: pointer;" title="Click to toggle collapse/expand day summaries for this store.">
<td ng-repeat="col in headerList2" ng-switch="col">
<span ng-switch-when="lstDetail"> <button type="button" ng-click="btnViewDetails_Click(index)" class="btn btn-sm btn-info">+</button></span>
<span ng-switch-default>{{ client[col] }}</span>
</td>
</tr>
<tr>
<td colspan="3">
<table class="table table-striped table-bordered table-hover" dt-instance="dtInstance3" id="dtInvoicingData3" dt-options="dtOptions3" dt-column-defs="dtColumnDefs3">
<thead>
<tr>
<th ng-repeat="col3 in headerList3">{{col3 | translate}} </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(index,client) in lstChildInvoiceDetail" class="clickableRow" style="cursor: pointer;" title="Click to toggle collapse/expand day summaries for this store.">
<td ng-repeat="col3 in headerList3" ng-switch="col">
<!-- <span ng-switch-when="lstDetail"> <button type="button" ng-click="btnViewDetails_Click(index)" class="btn btn-sm btn-info">+</button></span> -->
<span ng-switch-default>{{ client[col3] }}</span>
</td>
</tr>
</tbody>
</table>
</td>
<td style="display:none;"> </td>
<td style="display:none;"></td>
</tr>
</tbody>
</table>
Child Table is created on first row, i want to created on each row.
Do you have any idea about it?

Because you are trying to create two rows with different structures instead of nested tables.
Row 1 :
<tr ng-repeat="(index,client) in lstInvoiceDetail" class="clickableRow" style="cursor: pointer;" title="Click to toggle collapse/expand day summaries for this store.">
<td ng-repeat="col in headerList2" ng-switch="col">
<span ng-switch-when="lstDetail"> <button type="button" ng-click="btnViewDetails_Click(index)" class="btn btn-sm btn-info">+</button></span>
<span ng-switch-default>{{ client[col] }}</span>
</td>
</tr>
And Row 2 :
<tr ng-show="showViewDetail">
<div class="span12 pull-right" ng-show="showViewDetail">
<table datatable="ng" class="table table-striped table-bordered table-hover" dt-instance="dtInstance3" id="dtInvoicingData3" dt-options="dtOptions3" dt-column-defs="dtColumnDefs3">
<thead>
<tr>
<th ng-repeat="col3 in dtColumnDefs3">{{col3.aTargets[0].sTitle | translate}} </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(index,client) in lstInvoiceDetail" class="clickableRow" style="cursor: pointer;" title="Click to toggle collapse/expand day summaries for this store.">
<td ng-repeat="col3 in headerList3" ng-switch="col">
<span ng-switch-when="lstDetail"> <button type="button" ng-click="btnViewDetails_Click(index)" class="btn btn-sm btn-info">+</button></span>
<span ng-switch-default>{{ client[col3] }}</span>
</td>
</tr>
</tbody>
</table>
</div>
</tr>
and as far error states, data in both rows has different count for header and columns. It means your lists dtColumnDefs2, headerList2, dtColumnDefs3, and headerList3 have different counts.

Related

Ng-show not showing product's detail

I'm making an exercise about the AngularJS, and i created a table that will load the data from database, i have a "Detail" button, when i click on that button, it will assign a new row below the row which contain a button i clicked. It's work fine but the problem is when i click the "Detail" button, it the detail of all, i just want it to show the detail of which product i clicked.
Here is my HTML code:
var app = angular.module("dataApp", []);
app.controller("dataExcuteController", function ($scope, $window,$http) {
$http.get('http://localhost:8080/sachonline/public/administrator/theloai/dstheloai').then(function (response) {
$scope.theloai = response.data.message.ds_theloai;
$scope.isLoading = false;
});
$scope.detailtheloai = function (item) {
$scope.showdetail = true;
};
});
<body ng-app="dataApp" ng-controller="dataExcuteController">
<div class="container">
<table class="table table-bordered">
<thead class="text-center">
<th>STT</th>
<th>Tên thể loại</th>
<th>Trạng thái</th>
<th>
<span><i class="fa fa-cog text-muted"></i></span>
</th>
</thead>
<tbody ng-repeat="item in theloai">
<tr>
<td class="text-center">#{{ item.tl_ma }}</td>
<td>#{{ item.tl_ten }}</td>
<td class="text-center" ng-if="item.tl_trangThai==1">
<span><i class="fa fa-check-circle text-success"></i></span>
</td>
<td class="text-center" ng-if="item.tl_trangThai==0">
<span><i class="fa fa-times-circle text-danger"></i></span>
</td>
<td class="text-center">
<button type="button" class="btn btn-sm btn-warning text-white mr-3 pt-0 pl-2 pr-2" ng-click="detailtheloai(item)"><i class="fa fa-info-circle"></i></button>
<button type="button" class="btn btn-sm btn-success text-white mr-3 pt-0 pl-2 pr-2" data-toggle="modal" data-target="#editForm" ng-click="edittheloai($index)"><i class="fa fa-edit"></i></button>
<button type="button" class="btn btn-sm btn-danger text-white pt-0 pl-2 pr-2" ng-click="removetheloai($index)"><i class="fa fa-trash"></i></button>
</td>
</tr>
<tr ng-show="showdetail">
<td colspan="4">
<table class="table table-info table-bordered">
<tbody>
<tr>
<th class="text-right">Mã thể loại:</th>
<td>#{{ item.tl_ma }}</td>
</tr>
<tr>
<th class="text-right">Tên thể loại:</th>
<td>#{{ item.tl_ten }}</td>
</tr>
<tr>
<th class="text-right">Trạng thái:</th>
<td class="text-center" ng-if="item.tl_trangThai==1">
<span><i class="fa fa-check-circle text-success"></i></span>
</td>
<td class="text-center" ng-if="item.tl_trangThai==0">
<span><i class="fa fa-times-circle text-danger"></i></span>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
<script src="{!!asset('js/showlist.js')!!}"></script>
</body>
You need to store the show value for every item, therefore I propose you this changes:
js:
$scope.detailtheloai = function (item) {
item.showdetail = true;
};
html:
<tr ng-show="item.showdetail">

Search on bootstrap table with expanding rows

I have a bootstrap table with expanding rows. Each row can expand into multiple rows, and those can too expand in multiple rows (3 levels in total).
The search does find items on the 3rd level but it doesn't display them correctly.
This is an example code on codepen.
https://codepen.io/anon/pen/gGOOBz
My HTML code is:
<table st-table="displayedCollection" st-safe-src="domains" class="table table-condensed" style="border-collapse:collapse;">
<thead>
<tr>
<th st-sort="name">Domains</th>
</tr>
<tr>
<th colspan="5"><input st-search="" class="form-control" placeholder="Search ..." type="text" /></th>
</tr>
</thead>
<tbody ng-cloak>
<tr ng-repeat-start="row in displayedCollection">
<td id="package1-{{$index}}" class="accordion-toggle data-exists cursor-pointer" data-toggle="collapse" data-parent="#OrderPackages-{{$index}}" data-target=".packageDetails1-{{$index}}">{{row.name}}
</td>
</tr>
<tr ng-repeat-end>
<td id="package2-{{$index}}" colspan="3">
<div class="accordion-body collapse packageDetails1-{{$index}} + 1">
<table st-table="beansCollection" st-safe-src="types" class="table table-condensed" style="border-collapse:collapse;">
<!--<thead>
<tr>
<th st-sort="name">Types</th>
</tr>
</thead>-->
<tbody>
<tr ng-repeat-start="beanType in row.beans">
<td id="type1-{{$index}}" class="accordion-toggle" data-toggle="collapse" data-parent="#typePackages-{{$index}}" data-target=".typesDetails1-{{$index}}">
{{beanType.name}}
</td>
<td align="right">
<button ng-click="getBeanName(beanType.name, null, beanType)" data-toggle="modal" data-target="#myModal" type="button" class="btn btn-default" ng-if="showButton(beanType.beans)">
Display
</button>
</td>
</tr>
<!---->
<tr ng-repeat-end ng-visible="false">
<td id="typeId2-{{$index}}" colspan="3">
<div class="accordion-body collapse typesDetails1-{{$index}} + 1">
<table class="table table-condensed">
<tbody>
<tr ng-repeat="leafBean in beanType.beans">
<td>
{{leafBean.name}}
</td>
<td align="right">
<button ng-click="getBeanName(beanType.name, leafBean.name, leafBean)" data-toggle="modal" data-target="#myModal" type="button" class="btn btn-default">Display</button>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
I want that when I search something under a certain row it would be displayed with the row above already expanded.
PHOTO:
Say I want to search for TBLEXCHANGEMEMBERSHIPS which is on the 3rd level.
When I input it into the search bar, it finds it but doesn't display it correctly.
What should I do?

ng-repeat and collapse table

I am trying to display information inside a table using a button to show and hide the data in each row using the row's id, but since I have 2 ng-repeat, the first loop is completed before the second and therefore all the data is displayed in the same row : here is my code :
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th></th>
<th>Projet</th>
<th>Responsable Apitech</th>
<th>Temps Passé</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="p in projetsListe" >
<td>
<button class="btn btn-xs" ng-click="expanded = !expanded" expand data-toggle="collapse" id="{{p.IdProjet}}" data-target=".{{p.IdProjet}}">
<span ng-bind="expanded ? '-' : '+'"></span>
</button>
</td>
<td>{{p.NomProjet}}</td>
<td>{{p.ResponsableApitech}}</td>
<td>Temps Passé</td>
</tr>
<tr ng-repeat-end ng-show="expanded">
<td></td>
<td colspan="6">
<table class="table table-condensed table-bordered">
<thead>
<th></th>
<th>Tache</th>
<th>Collaborateur</th>
<th>Date</th>
<th>Temps Passé</th>
</thead>
<tbody>
<tr ng-repeat= "ft in ftListesorted" ng-show="expanded" class="collapse {{ft.IdProjet}}">
<td><i class="glyphicon glyphicon-plus"></i></td>
<td>{{ft.NomTache}}</td>
<td>{{ft.NomCollaborateur}}</td>
<td>{{ft.Datefeuillestemps | date : 'dd/MM/yyyy' }}</td>
<td>{{ft.TempsPasse}}</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
This is what im trying to achieve : http://embed.plnkr.co/qqNGSbw6oLUZbKqVQVpG/?show=preview
In my case :
This is what I get instead :
If you noticed in the second image get the information of the first and the second row while i want the information of each row seperatly.
Here is a plunker with an example of the problem : https://plnkr.co/edit/pPcPipLK0TltnOC60SSf
create expanded property for each row. Change this lines
<button class="btn btn-xs" ng-click="p.expanded = !p.expanded" expand data-
toggle="collapse" id="{{p.IdProjet}}" data-target=".{{p.IdProjet}}">
and
<tr ng-repeat-end ng-show="p.expanded">

Why I get gap in table rows?

I work on my angularjs project.
I use ng-repeat to create rows in table.
Here is plunker.
Here is html template:
<table class="table table-responsive table-hover">
<thead>
<tr>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="object in arr1 track by object.id">
<td class="pull-left" ng-bind="object.name"></td>
<td ng-class="{'wrapper':showReview != $index }">
<div ng-class="{'slide':showReview != $index}">
<a class=" btn btn-default btn-xs" ng-click="showReview = showReview == $index ? -1 : $index;"><i class="glyphicon glyphicon-camera"></i></a>
<a class=" btn btn-default btn-xs" ng-click="showInspections = !showInspections; showReview = showReview == $index ? -1 : $index;"><i class=" glyphicon glyphicon-list-alt"></i></a>
</div>
</td>
</tr>
<tr ng-repeat-end ng-if="showInspections && showReview == $index">
<td colspan="">
{{t}}-{{$index}}
</td>
</tr>
</tbody>
</table>
Here is controller:
app.controller('MainCtrl', function($scope) {
$scope.arr1 = [{id:'124',name:'qqq'},
{id:'589',name:'www'},
{id:'45',name:'eee'},
{id:'567',name:'rrr'}];
$scope.t=100;
});
Here how it looks in the view:
You can see in picture above I have gap between the rows and I cant figure out why I get this gap?
You have one th in head and one td in second row you need to add colspan="2" on both of them.
Also do not use class="pull-left" with td take another element inside td and make it pull-left

How to convert an existing table(Html) to jQuery datatable in AngularJS

Below is the html I have used to show data in the table, its working fine.
Now I want to convert it to jQuery Datatables.
HTML:-
<table cellpadding="3" class="table table-bordered">
<thead>
<tr class="success">
<th style="cursor: pointer;" ng-click="sort('DOB')"><b>DOB</b> <span class="glyphicon sort-icon" ng-show="sortKey=='DOB'" ng-class="{'glyphicon-chevron-up':reverse,'glyphicon-chevron-down':!reverse}"></span></th>
<th style="cursor: pointer;" ng-click="sort('StateName')"><b>State</b> <span class="glyphicon sort-icon" ng-show="sortKey=='StateName'" ng-class="{'glyphicon-chevron-up':reverse,'glyphicon-chevron-down':!reverse}"></span></th>
<th style="cursor: pointer;" ng-click="sort('FileId')"><b>Image</b> <span class="glyphicon sort-icon" ng-show="sortKey=='FileId'" ng-class="{'glyphicon-chevron-up':reverse,'glyphicon-chevron-down':!reverse}"></span></th>
<th><b>Actions</b></th>
</tr>
</thead>
<tbody>
<tr dir-paginate="employee in employees|orderBy:sortKey:reverse|filter:search|itemsPerPage:5" ng-model="search">
<td>{{employee.DOB | date:'MM/dd/yyyy' }}
<td>{{employee.StateName}}
</td>
<td>
<img ng-src="UploadedFiles/{{employee.FilePath}}" class="img-circle" style="max-width: 50px" alt='Employee Image Missing' />
</td>
</tr>
</tbody>
</table>

Resources