Add a button to show additional data in data tables - arrays

i am not much familiar with Data Tables but by following the examples provide i manged to load the data set to my table via an json. now my problem is i have some additional data to show when a button in a row clicked.lets say i view club details when i click on show members button which is in each raw i need to show members details from the json file.How can i achieve this.Sorry if i am repeating a question but couldn't find one here.if you can provide me certain resources which address a slimier problem i'll appreciate. Thanks!
my json seems like.
{
"data": [
{
"club": [
"xxxxx",
"xxxxx"
],
"members":[{"a":{"fname":"AAA","lname":"BBB"},"b":{"fname":"AAA","lname":"BBB"},"c":{"fname":"AAA","lname":"BBB"}}],
"address": [
"xxxx",
"xxxxx",
"xxxxxx"
],
"district": "xxxxx",
"established": "xxxx"
},
{
"club": [
"xxxxx",
"xxxxx"
],
"members":[{"a":{"fname":"AAA","lname":"BBB"},"b":{"fname":"AAA","lname":"BBB"},"c":{"fname":"AAA","lname":"BBB"}}],
"address": [
"xxxx",
"xxxxx",
"xxxxxx"
],
"district": "xxxxx",
"established": "xxxx"
}
]}
my script to load data as follows.
<script>
$(document).ready(function() {
$('#example').DataTable( {
"ajax": "spellData.json",
"columns": [
{ "data": "club[, ]" },
{ "data": "address.0" },
{ "data": "members[, ]" },
{ "data": "district" },
{ "data": "established" },
{ "data": "address.2" },
{ "data": "address.1" }
]
} );
} );
</script>
my table is as follows.
<table id="example" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th>Club Name</th>
<th>Area</th>
<th>Members</th>
<th>District</th>
<th>Estb.</th>
<th>Address</th>
<th>Town</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Club Name</th>
<th>Area</th>
<th>Members</th>
<th>District</th>
<th>Estb.</th>
<th>Address</th>
<th>Town</th>
</tr>
</tfoot>
</table>
here if i can use a dialog to load member data its easy because i may need to add some columns too.How i can achieve something like this?HEre is a jsfiddle if you need..

You were nearly there but the alert was due to reinitialising the child DataTable. If you initialise it on page load and then interact with it when the button is clicked it's much better as you'll then not have to check to see if it's been initialised already:
var e = $('#sub_table').DataTable({
"columns": [{
"data": "fname",
"title": "First Name"
}, {
"data": "lname",
"title": "Last Name"
}]
});
Then, when your button is clicked you can clear the table, add the rows (might be better to have members being an array here, then you could add them all in one go using rows.add() which accepts an array rather than an object) and finally draw it again. As things stand this works:
$('table.table').on('click', '.mybutton', function() {
e.clear();
$.each(example.row($(this).parents('tr')).data().members, function(k, v) {
e.row.add(v);
});
e.draw();
});
Working JSFiddle, hope that helps.

Related

Using ng-repeat on nested array of objects

Below is my JSON object and I am trying to show the same in html table.
$scope.results = {
"data": [
{
"name": "Sam",
"details": [
{
"official": [
{
"address1": "Link road",
"pincode": 76755554
},
{
"address1": "K main road",
"pincode": 9766565
}
]
},
{
"name": "John",
"details": [
{
"official": [
{
"address1": "Old college road",
"pincode": 11111
},
{
"address1": "near east side",
"pincode": 6555446
}
]
}
]
}
]
}
]
}
I have used ng-repeat to achieve the below output. But I am not getting the expected result
This is the code which I have tried and got stuck JSFIDDLE
Any idea on how to achieve my expected result will be really helpful.
You may have to tweak this slightly if your data structure can get more complicated when there are more levels, but this should reformat your data and flatten everything into an array of people without all the different levels.
$scope.peopleFlat = [];
function flattenPeople(people) {
people.forEach((person) => {
$scope.peopleFlat.push({
name: person.name,
addresses: person.details[0].official
});
if (person.details.length > 1) {
flattenPeople([person.details[1]]);
}
});
}
flattenPeople($scope.people);
Then you can use a combination of ng-repeat-start and ng-repeat-end to make it work using rowspan instead of a nested <table> element.
<table class="table table-bordered table-condensed">
<tr>
<th>Name</th>
<th>Address</th>
<th>Pincode</th>
</tr>
<tr ng-repeat-start="person in peopleFlat">
<td rowspan="{{person.addresses.length || 1}}">{{person.name}}</td>
<td>{{person.addresses.length ? person.addresses[0].address1 : ''}}</td>
<td>{{person.addresses.length ? person.addresses[0].pincode : ''}}</td>
</tr>
<tr ng-repeat-end ng-repeat="address in person.addresses.slice(1)">
<td>{{address.address1}}</td>
<td>{{address.pincode}}</td>
</tr>
</table>

retrieve JSON list with absent Object and replace them by null using Angular2

Here is my JSON array :
"user" : {
"id": 456,
"nickname": "xxx",
"pf": {
"id": 123,
"account": [
{
"accountid": 1494235749,
"status": "New",
"accountnbr": 12345,
"cyc": {
"cycid": 1494404053,
"active": true,
"status": "New",
"name": "QST192017",
},
},
{
"accountid": 1494403399,
"status": "New",
"accountnbr": 915177,
"cyc": {
"cycleid": 1494406299,
"active": true,
"status": "Closed",
"name": "QSL342014"
}
},
{
"accountid": 1494500399,
"status": "New",
"accountnbr": 90010,
}
]
},
}
And this is what I have in my template :
<tr *ngFor="let account of accounts">
<td>{{ account.accountnbr }}</td>
<td>{{ account.cyc.name}}</td>
</tr>
I tried to retrieve a list of all my accounts , and as you can see one of the account has no cyc, and shows an error , any idea how to replace absent JSON object by null in the list ?
PS : I'm using angular2
Thank you.
/K
use account.cyc?.name will solve your problem. when account doesn't have cyc, your template will just show blank without any error.
see documentation of safe-navigation-operator(?).
<tr *ngFor="let account of accounts">
<td>{{ account.accountnbr }}</td>
<td>{{ account.cyc?.name}}</td>
</tr>
This is as simple as using an *ngIf:
<div *ngFor="let acc of account">
<div *ngIf="!acc.cyc">NO CYC ON THIS ACCOUNT</div>
</div>
For this purpose an absent object is null/undefined.
You could also map over the object in your component and set it as null:
account.map(x =>{
if(!x.cyc){
x.cyc = null;
}
return x;
});

how to get particular customers order

/*factory method for getting particular customers order*/
factory.getCustomer = function(customerId) {
for(var i=0,len=customers.length ; i<len ; i++) {
if(customers[i].id === parseInt(customerId)){
return customer[i];
}
}
return {};
};
return factory();
/*Controller*/
myApp.controller('OrdersController',['$scope','$routeParams','customersFactory', function($scope,$routeParams,customersFactory) {
var customerId = $routeParams.customerId;
$scope.customer = null;
function init() {
$scope.customer = customersFactory.getCustomer(customerId);
}
init();
}]);
/*View*/
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>{{customer.name}}'s Orders</h2>
<table class="table table-hover">
<tr>
<th>Product</th>
<th>Total</th>
</tr>
<tr ng-repeat="order in customer.orders">
<td>{{ order.product }}</td>
<td>{{ order.total | currency }}</td>
</tr>
</table>
</div>
</div>
</div>
/*JSON FILE*/
{
"id": "1",
"joined": "2000-12-2",
"name": "Wali",
"city": "Dubai",
"orderTotal": "9.0765",
"orders": [
{
"id": "1",
"product": "protein",
"total": "11.987"
}
]
},
{
"id": "2",
"joined": "2004-12-2",
"name": "Ali",
"city": "London",
"orderTotal": "20.0765",
"orders": [
{
"id": "2",
"product": "bcca",
"total": "2.3456"
},
{
"id": "3",
"product": "baseball",
"total": "4.3456"
}
]
},
{
"id": "3",
"joined": "1980-11-2",
"name": "Zen",
"city": "Australia",
"orderTotal": "6.500",
"orders": [
{
"id": "3",
"product": "chocolate",
"total": "6.4567"
}
]
}
I have made a customers table from which we can perform the CRUD functionality, but when I click to check the particular customer order it is redirecting me to the right view via routing but particular customers orders are not displaying.
can any one suggest a solution for this?
According to your JSON data, the ID is a String, but you are parsing it into an integer, and using ===, which will match only if the value and the type of the compared variables match.
You need to change the if statement, one option is:
if (parseInt(customers[i].id) === parseInt(customerId))
Another option will be:
if (customers[i].id == customerId)
And yet another option is using angular's $filter service.
You need to inject it into your factory, and than in order to get the client, you can use:
var customer = $filter('filter')(customers, {id: customerId.toString()}, true);
return customer.length === 1 ? customer[0] : null;
The toString part is only because your JSON data have ID as as string, and the third argument is set to true to prevent 'like' filter (default $filter behavior will return id 10 for example also if the customerId is 1).

Get value in a row on click and pass it to popup

I need to get the value in a row of a table on click and display it in popup
HTML:
<md-data-table-container>
<table md-data-table class="md-primary" md-progress="deferred">
<thead md-order="query.order" md-trigger="onorderchange">
<tr>
<th name="Task To Be Done"></th>
<th name="Office"></th>
<th name="Due Date"></th>
</tr>
</thead>
<tbody ng-click="showAlert($event)">
<tr ng-repeat="dessert in desserts.data" ng-click="showAlert($index)" flex-sm="100" flex-md="100" flex-gt-md="auto">
<td>{{dessert.task}}</td>
<td></td>
<td>{{dessert.due_on}}</td>
</tr>
</tbody>
</table>
</md-data-table-container>
JS:
$scope.desserts = {
"count": 6,
"data": [{
"task": "Frozen yogurt",
"type": "Ice cream"
}, {
"task": "Ice cream sandwich",
"type": "Ice cream"
}, {
"task": "Eclair",
"type": "Pastry"
}, {
"task": "Cupcake",
"type": "Pastry"
}, {
"task": "Jelly bean",
"type": "Candy"
}, {
"task": "Lollipop",
"type": "Candy"
}, {
"task": "Honeycomb",
"type": "Other"
}]
};
$scope.showAlert = function (index) {
$scope.obj = $scope.desserts.data[2];
$scope.task = $scope.obj.task;
alert($scope.task);
console.log($scope.task);
};
issue in my code is that i could get the value on the array which i have specified ".data[2]". Actually when i click a row in my table i need that value to be displayed to popup "sweetAlert". is there any solution
Don't pass the $index, as this can be a bit dangerous if the underlying data changes, and in this case it just forces you to re-get the item from the array.
Pass the actual item you want to display back to the alert.
<tr ng-repeat="dessert in desserts.data" ng-click="showAlert(dessert)" flex-sm="100" flex-md="100" flex-gt-md="auto">
<td>{{dessert.task}}</td>
<td></td>
<td>{{dessert.due_on}}</td>
</tr>
Don't assign to scope unless you really need it elsewhere.
$scope.showAlert = function (dessert) {
alert('Task:' + dessert.task);
// if you're just using a variable in this function, declare it locally
var dessertType = dessert.type;
console.log(dessertType);
};
See an example of $index causing issues:
http://codeutopia.net/blog/2014/11/10/angularjs-best-practices-avoid-using-ng-repeats-index/comment-page-1/

Creating check box grid using ng-repeat

The Json structure,
[
{
"name": "module1",
"categories": [
{
"name": "cat1"
},
{
"name": "cat4"
}
]
},
{
"name": "module2",
"categories": [
{
"name": "cat3"
},
{
"name": "cat4"
}
]
},
{
"name": "module3",
"categories": [
{
"name": "cat1"
},
{
"name": "cat2"
},
{
"name": "cat4"
}
]
}
]
Using this Json structure, I need to display a grid of checkboxes as follows,
On click of any checkbox, I should be able to alert the corresponding category & module name. If each module has all four categories then I can easily use nested ng-repeat and display the structure (You can check it here. ). But here the number of categories differs for each module. Could you please suggest a way to implement this functionality?
Need to find the number of categories first and display it as the headers in the table
Display checkbox exactly at the right place
It is possible to have an ng-repeat iterate over the result of a function - in contrast to an array field in the scope - like this:
<tr ng-repeat="module in getAllModules()">
<td ng-repeat="cat in getAllCategories()">
<!-- display checkbox here if required -->
</td>
</tr>
I think it should be clear how to implement the two methods. However, you have to consider the performance overhead involved because the total set of modules and categories is calculated over and over again.
I think lex answer is corrrect. If I understood his solution right,the getAllCategories method is the interesting part. It has to return ALL categories, while getAllModules can still return your modules Array.
<tr ng-repeat="module in modules">
<td ng-repeat="cat in getAllCategories()">
<input type="check" ng-if="module.containsCat(cat)">
</td>
</tr>
with the containsCat method being something like
$scope.containsCat = function(module, cat){
for each(var moduleCat in module.categories ){
if(moduleCat.name === cat) return true;
}
return false;
}

Resources