I have a rest response which i want to loop over but based on condition, here's my response:
{
"veichleType": "SUV",
"veichleBrand": "BMW",
"veichleModels": [{
"veichleModel": "M3",
"property1": "value",
"property2": "value",
"property3": "value"
},
{
"veichleModel": "M1",
"property": "value",
"property2": "value",
"property3": "value"
}
]
}
I want in the UI to show only one object based on veichleModel if user searched by M3 then display that object response in the table, else show M1.
<table>
<thead>
headings here
</thead>
<tbody *ngIf='serviceResponse.veichleModels'>
<tr *ngFor="let veichleModel of serviceResponse.veichleModels">
<td>{{veichleModels.property1}}</td>
<td>{{veichleModels.property2}}</td>
<td>{{veichleModels.property3}}</td>
</tbody>
</table>
You need to do two things here :
Add some variable to store the selected model M1 or M3
Add condition inside loop to display respective object properties (Make use of ng-container)
Doing so, you can scale your array to 100 or more objects
template
<tbody *ngIf='serviceResponse.veichleModels'>
<tr *ngFor="let veichle of serviceResponse.veichleModels">
<ng-container *ngIf="veichle.veichleModel == selected">
<td>{{veichle.property1}}</td>
<td>{{veichle.property2}}</td>
<td>{{veichle.property3}}</td>
</ng-container>
</tr>
</tbody>
ts file
export class AppComponent {
selected = 'M1';
serviceResponse = {"veichleModels": [{
"veichleModel": "M3",
"property1": "M3val1",
"property2": "M3val2",
"property3": "M3val3"
},
{
"veichleModel": "M1",
"property1": "M1val1",
"property2": "M1val2",
"property3": "M1val3"
}
]}
}
Related
I've been struggling with this code. I need to avoid specific columns from being exported. I have done that but I don't know how to export the text inside any input element.
Here is the code:
$("#campaignMaterialsTable table").DataTable({
dom: 'Bfrtip',
buttons: [
{
extend: 'excel',
className: 'export-button',
text: 'Export as Excel',
columns: ':not(.notexport)',
//exportOptions: {
// format: {
// body: function (data, row, column, node) {
// //
// //check if type is input using jquery
// return $(data).is("input") ?
// $(data).val() :
// data;
// },
// columns: ':not(.notexport)'
// }
//},
title: 'Campaign Materials'
}]
});
I don't know here to put the code at the right place.. while initializing..
I referred to this links, but still not getting what I want:
https://datatables.net/forums/discussion/50724/export-values-typed-in-input-box-excelhtml5
https://datatables.net/forums/discussion/42205/export-data-with-text-box-in-td-of-data-table#latest
https://datatables.net/extensions/buttons/examples/html5/outputFormat-function.html
https://datatables.net/forums/discussion/50724/export-values-typed-in-input-box-excelhtml5
I assume you have a DataTable containing one or more input fields, something like this:
The user can type values into the input fields.
You want to export data to Excel, so that the result looks like this:
Here we can see the user-provided data as well as the standard table data.
To achieve this, I used the following table data:
<table id="example" class="display nowrap dataTable cell-border" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>Adélaïde Nixon</td>
<td>System Architect</td>
<td><input type="text" id="office" name="office"></td>
<td>432434</td>
<td>2011/04/25</td>
<td>$320,800</td>
</tr>
<tr>
<td>John Smith</td>
<td>Maager</td>
<td><input type="text" id="office" name="office"></td>
<td>6123</td>
<td>2011/04/25</td>
<td>$320,800</td>
</tr>
<tr>
<td>John Smith 2</td>
<td>Director</td>
<td><input type="text" id="office" name="office"></td>
<td>6123</td>
<td>2011/04/25</td>
<td>$320,800</td>
</tr>
</tbody>
</table>
And I used the following DataTable initialization code:
<script type="text/javascript">
$(document).ready(function() {
$('#example').DataTable({
dom: 'Bfrtip',
buttons: [
{
extend: 'excel',
exportOptions: {
format: {
body: function ( inner, rowidx, colidx, node ) {
if ($(node).children("input").length > 0) {
return $(node).children("input").first().val();
} else {
return inner;
}
}
}
}
}
]
});
});
</script>
The body function assumes that, for input fields, there is only an input field in the cell (i.e. the input field is not contained in a form or any other element).
It uses the node parameter to check for input data, to avoid data formatting issues that could occur (e.g. with dates). I recommend doing that rather than using $(data).is("input").
If there is no input field found in the cell, then the cell contents (inner) are returned.
If the structure of your table does not match these assumptions, then you may need to adjust the above code, of course.
Edit
Regarding the follow-up question about choosing which columns to export, there are various ways.
You can hard-code the column indexes you want to export (where index 0 means the first column). For example:
exportOptions: {
columns: [ 0, 1, 2, 3, 5 ],
format: {
body: function ( inner, rowidx, colidx, node ) {
if ($(node).children("input").length > 0) {
return $(node).children("input").first().val();
} else {
return inner;
}
}
}
}
This exports all columns apart from the Start Date column (index 4).
Or you can use the approach in your question, based on a class, I believe. I have not actually tried that one.
Take note of where the columns: [ 0, 1, 2, 3, 5 ] directive is placed - it is inside the exportOptions section.
you can use
exportOptions:{
columns: ':visible'
}
in below buttons
buttons: [
{
extend: 'pdf',
footer: true,
exportOptions: {
columns: ':visible'
}
},
it will export only visible columns
I want to output this JSON data to a table.
I do not know how to put the contents of "fields" into the same Tr tag.
{
"page": [
{
"type": "Type A",
"fields": [
{
"type": "Type1",
"code": "field1",
"size": {
"width": "200",
"height":"50"
}
},
{
"type": "Type2",
"code": "field2",
"size": {
"width": "250",
"height":"50"
}
}
]
},
{
"type": "Type B",
"fields": [
//....
]
}
],
"revision": "1"
}
I wrote this html
<table>
<thead>
<tr>
<th>Parent-Type</th>
<th>Child-Type</th>
<th>code</th>
<th>width</th>
<th>height</th>
</tr>
</thead>
<tbody id="my-tbody" v-cloak>
<tr v-for="(item, i) in rowData">
<td>
{{item.type}}
</td>
<td v-for="(field, j) in Object.keys(item.fields)">
{{field.code}}
</td>
</tr>
</tbody>
</table>
<scprit>
(() =>{
new Vue({
el: "#my-tbody",
data: {
rowData: []
},
created() {
let _self = this
getLayout().then(function (resp) {
_self.rowData = resp.page;
});
}
});
})();
</script>
I want to create a tr tag for each "page" ,and a td tag for each "fields".
Is it better to format in single-tiered JSON and set it in data?
Thanks.
Try something like this:
<table>
<thead>
<tr>
<th>Parent-Type</th>
<th>Child-Type</th>
<th>code</th>
<th>width</th>
<th>height</th>
</tr>
</thead>
<tbody id="my-tbody" v-cloak>
<tr v-for="item in rowData" :key="item.type">
<td>
{{item.type}}
</td>
<td v-for="field in item.fields" :key="field.code">
{{field.code}}
</td>
</tr>
</tbody>
</table>
Regards
I have a table:
<table class="table table-bordered table-hover" id="user-table">
<thead>
<tr>
<th data-field="id">Id</th>
<th data-field="name">Name</th>
<th data-field="email">Email</th>
<th data-field="company">Company</th>
<th data-field="actions">Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>John Doe</td>
<td>john#doe.com</td>
<td>Doe Inc.</td>
<td>
<div class="btn-group">
<i class="fa fa-pencil"></i>
</div>
</td>
</tr>
</tbody>
</table>
My current way to add row:
var columns = $.map(data,function(v,k){
return v;
});
var rowNode = table.row.add(columns).order([0, 'desc']).draw(false).node();
$(rowNode).addClass('selected');
setTimeout(function(){$(rowNode).removeClass('selected');}, 2000);
My data looks like this:
{
"data":[ {
"id": 2,
"name": "Jane Doe",
"email": "jane#doe.com",
"company": "Doe Inc."
}
]
}
Is there a way to add row based on columns? Instead of returning v on a mapped data, I can directly insert data[0] using row.add(). I've been searching but can't get the exact scenario.
Apparently, the purpose is for shuffled data. In a table that have 15 columns, I don't have to worry about the proper column arrangements.
I found this https://datatables.net/reference/api/row.add() example #1 but obviously the documentation says:
Data to use for the new row. This may be an array, object, Javascript object instance or a tr element. If a data structure is used (i.e. array or object) it must be in the same format as the other data in the table (i.e. if your table uses objects, pass in an object with the same properties here!).
If you specify columns (or columnDefs) with data attributes, you can add row or rows in JSON / object literal format:
columns: [
{ data: 'id' },
{ data: 'name' },
{ data: 'email' },
{ data: 'company' }
]
You must also specify the last column, even it is not targeting any data. You can use render(), createdCell() or defaultContent:
const actions = `
<div class="btn-group">
<i class="fa fa-pencil"></i>
</div>
`;
var table = $('#user-table').DataTable({
columns: [
{ data: 'id' },
{ data: 'name' },
{ data: 'email' },
{ data: 'company' },
{ data: null, defaultContent: actions }
]
...
})
Now you can insert data from above:
var rowNode = table.row.add(data.data[0]).order([0, 'desc']).draw(false).node();
or all rows :
table.rows.add(data.data).draw()
I am using Datatables API but am not able to add multiple buttons in one row.
var table = $('#table_invdata').DataTable({
"columnDefs": [{
"targets": -1,
"data": null,
"defaultContent":
'<button class="btn-view" type="button">EDIT</button>'
}]
});
Try this code
var table = $('#table_invdata').DataTable({
"columnDefs": [{
"targets": -1,
"data": null,
"defaultContent":
'<button class="btn-view" type="button">EDIT</button>'
+ '<button class="btn-delete" type="button">Delete</button>'
}]
});
Or
var table = $('#table_invdata').DataTable({
"columnDefs": [{
"targets": -1,
"data": null,
"defaultContent":
'<button class="btn-view" type="button">EDIT</button> <button class="btn-delete" type="button">Delete</button>'
}]
});
Update :
You can use datatable render function to update the column values.
<table class="table" id="datatable" >
<thead>
<tr>
<th>Name </th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Jquery Datatable Code :
$('#datatable').DataTable ({
"data" : FinalResult,
"columns" : [
{ "data" : Name},
{ "data" : null,render: function ( data, type, row ) {
return '<button class="btn-view" type="button">EDIT</button>';
} },
{ "data" : null,render: function ( data, type, row ) {
return '<button class="btn-delete" type="button">Delete</button>';
} }
]
});
Fiddel Link : https://jsfiddle.net/jijomonkmgm/j6madey4/
<table id="table_invdata" class="table table-striped table-bordered">
<tr>
<th>EmpID</th>
<th>EmpName</th>
<th>Email-id</th>
<th>Salary</th>
<th>Position</th>
<th></th>
</tr>
</table>
Given the following code
// Assuming records is an array of objects
// Record is of the form {"fname": "John", "lname": "Smith", "dob": 1499994497871}
// Field mapper is
[
{
"name": "fname",
"label": "First Name",
"render": function(val){ return val}
},
{
"name": "lname",
"label": "Last Name",
"render": function(val){ return val}
},
{
"name": "dob",
"label": "Date of Birth",
"render": function(val){ return new Date(val).toDateString()}
}
]
// Assume findField returns the mapper instance for a given record in the records array
<div v-for="record in records">
<div>
<table class="table">
<tbody>
<tr v-for="(value, key) in record">
<th v-if="findField(key)">{{ findField(key).label }}</th>
<td v-if="findField(key)">{{ findField(key).render(value) }}</td>
</tr>
</tbody>
</table>
</div>
</div>
I'm making four calls to findField().
What's the Vue recommendation to storing variables inside looping structure?
In other words, after the first tr, something like:
let localInstance = findField(key)
One way is to use a component.
Vue.component("row", {
props:["map", "value"],
template:`
<tr>
<th v-if="map">{{ map.label }}</th>
<td v-if="map">{{ map.render(value) }}</td>
</tr>
`
})
And modify your template to use it.
<tr is="row" v-for="(value, key) in record"
:map="findField(key)"
:value="value">
</tr>
console.clear()
const fieldMap = [{
"name": "fname",
"label": "First Name",
"render": function(val) {
return val
}
},
{
"name": "lname",
"label": "Last Name",
"render": function(val) {
return val
}
},
{
"name": "dob",
"label": "Date of Birth",
"render": function(val) {
return new Date(val).toDateString()
}
}
]
const records = [{
"fname": "John",
"lname": "Smith",
"dob": 1499994497871
},
{
"fname": "John",
"lname": "Smith",
"dob": 1499994497871
},
{
"fname": "John",
"lname": "Smith",
"dob": 1499994497871
}
]
Vue.component("row", {
props: ["map", "value"],
template: `
<tr>
<th v-if="map">{{ map.label }}</th>
<td v-if="map">{{ map.render(value) }}</td>
</tr>
`
})
new Vue({
el: "#app",
data: {
records
},
methods: {
findField(key) {
return fieldMap.find(m => m.name === key)
}
},
})
<script src="https://unpkg.com/vue#2.2.6/dist/vue.js"></script>
<div id="app">
<div v-for="record in records">
<div>
<table class="table">
<tbody>
<tr is="row" v-for="(value, key) in record" :map="findField(key)" :value="value">
</tr>
</tbody>
</table>
</div>
</div>
</div>