Add rows to a JQuery Datatable - datatables

So basically, I get a little bit of idea about using data tables.
However, my question is a bit different based on my requirement. I'm not even sure whether it's possible.
As you may see inside the code, $("#tableContainer tbody").append(productList); basically creates a regular table (NOT a datatable).
Is there a way I can use productList directly inside a datatable so that it is created within the table standards?
$(document).ready(function() {
$.post('query-data.php', {
type: "view-products"
}, function(response) {
var productList;
var parsedResponse = JSON.parse(response);
for (i = 0; i < parsedResponse.length; i++) {
productList = $('<tr><td>' + (parsedResponse[i].IS_AVILABLE == 1 ? '<i class="fa fa-check fa-fw"></i>' : '<i class="fa fa-times" aria-hidden="true"></i>') + '</td><td>' + (parsedResponse[i].IMAGE_URL != "" && parsedResponse[i].IMAGE_URL ? '<i class="fa fa-check fa-fw"></i>' : '<i class="fa fa-times" aria-hidden="true"></i>') + '</td><td>' + parsedResponse[i].PRODUCT_ID + '</td><td>' + parsedResponse[i].NAME + '</td><td>' + parsedResponse[i].CATEGORY_NAME + '</td><td>' + parsedResponse[i].BUSINESS_NAME + '</td></tr>');
$("#tableContainer tbody").append(productList);
}
});
});
<table id="tableContainer" class="table hover view-menus">
<thead>
<tr>
<th>Avail</th>
<th>Img</th>
<th>Prod ID</th>
<th>Prod Name</th>
<th>Cat Name</th>
<th>Biz Name</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<th>Avail</th>
<th>Img</th>
<th>Prod ID</th>
<th>Prod Name</th>
<th>Cat Name</th>
<th>Biz Name</th>
</tr>
</tfoot>
</table>

Whooppie!! Turns out, it was quite simple.
First declare var table = $('table').DataTable(); before starting the for loop.
Then add table.row.add($(productList )).draw(); while iterating, i.e. inside the for loop. DONE! :)
var table = $('table').DataTable();
for (i = 0; i < parsedResponse.length; i++) {
productList = $('<tr><td>' + (parsedResponse[i].IS_AVILABLE == 1 ? '<i class="fa fa-check fa-fw"></i>' : '<i class="fa fa-times" aria-hidden="true"></i>') + '</td><td>' + (parsedResponse[i].IMAGE_URL != "" && parsedResponse[i].IMAGE_URL ? '<i class="fa fa-check fa-fw"></i>' : '<i class="fa fa-times" aria-hidden="true"></i>') + '</td><td>' + parsedResponse[i].PRODUCT_ID + '</td><td>' + parsedResponse[i].NAME + '</td><td>' + parsedResponse[i].CATEGORY_NAME + '</td><td>' + parsedResponse[i].BUSINESS_NAME + '</td></tr>');
table.row.add($(productList)).draw();
}

Related

I want to add new rows when add button is pressed, and with each added row a delete button should come to delete the row

This is my code in which I have defined a table
<table v-if="Object.keys(content_state).length >= 1" class="editable-table" id="table_value">
<thead>
<tr>
<th class="editable-tabidle-header">Field</th>
<th class="editable-table-header">Value</th>
</tr>
</thead>
<tbody>
<tr v-for="(pageDataItem, idx) in content_state" :key="idx" class="editable-table-row">
<td class="editable-table-data">
<div>{{pageDataItem.modified_keyword}}</div>
</td>
<td class="editable-table-data">
<div>
<b-form-input v-model="pageDataItem.formatted_text" #click="input_form($event)" id= "'pageDataItem.modified_keyword + idx'" :style="{'border': '2px solid rgb(' +
pageDataItem.color[0] + ',' + pageDataItem.color[1] + ',' +
pageDataItem.color[2] + ')', 'border-radius': '4px'}" v-on:dblclick="showModal($event, 0)" plaintext ></b-form-input>
</div>
<b-btn variant="success" #click="Add(id)" id="Add-button">Add</b-btn>
</td>
</tr>
</tbody>
</table>
And Javascript code is
public AddRow(id:any)
{
console.log(id)
var x =1;
let d = document.getElementById(id);
console.log(id)
let clone = d.firstElementChild.cloneNode(true);
clone.value = '';
clone.id= id+x;
this.last_added_row = clone.id;
d.appendChild(clone);
}
How should I add delete button with each new row generated? There should only be one add button per row and as many delete buttons as the input box.

get element id from template using smarty - Prestahop

I'm using Smarty in Prestashop. In my php file I built a function like this:
public function hookDisplayAdminOrderContentOrder($params)
{
$orderId = Tools::getValue('id_order'); // mi prendo l'id dell'ordine per le query sui docId
$query = 'SELECT docId1, docId1 FROM '._DB_PREFIX_.'orders WHERE id_order=\'' . $orderId . '\';';
$docId2 = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query)['docId2'];
$docId1 = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query)['docId1'];
$config_CreaOrdine = Configuration::get('PS_CREAZIONE_ORDINE');
$config_CreaFattura = Configuration::get('PS_CREAZIONE_FATTURA');
// uso order_documents per il contatore nel template
$order_documents = 0;
if ($docId1 || $docId2)
$order_documents++;
else if ($docId1 && $docId2)
$order_documents = 2;
if(!$docId1){
$message_order = 'documento NON salvato';
$submit_button_id = 'submit_order';
$submit_label = "Salva Ordine";
}else{
$message_order = 'documento salvato';
}
if(!$docId2){
$message_invoice = 'documento NON salvato';
$submit_button_id = 'submit_invoice';
$submit_label = "Salva Fattura";
}else {
$message_invoice = 'documento salvato';
}
smartyRegisterFunction($this->context->smarty, 'function', 'saveDocument', array($this, 'smartyDocument')); // aggiungo la funzione per salvare di nuovo l'ordine
$this->context->smarty->assign('id_order', $orderId);
$this->context->smarty->assign('config_CreaOrdine', $config_CreaOrdine);
$this->context->smarty->assign('config_CreaFattura', $config_CreaFattura);
$this->context->smarty->assign('order_documents', $order_documents); // contatore documenti salvati
$this->context->smarty->assign('order', $message_order);
$this->context->smarty->assign('order_docId', $docId1); //docId per tasto ordine
$this->context->smarty->assign('invoice', $message_invoice);
$this->context->smarty->assign('invoice_docId', $docId2); //docId per tasto fattura
return $this->display(__FILE__, 'views/templates/hook/admin_content_order.tpl');
}
Then in my admin_content_order.tpl I set the button name and id like this:
<div class="tab-pane" id="myplugin">
<table>
<tbody>
<thead>
<tr>
<td style="padding-left: 20px;"><strong>{l s='Stato ordine' mod='myplugin'} </strong></td>
<td style="padding-left: 20px;"><strong>{l s='Stato fattura' mod='myplugin'} </strong></td>
</tr>
</thead>
<tr>
<td style="padding-left: 20px;">{$order}</td>
<td style="padding-left: 20px;">{$invoice}</td>
</tr>
<tr>
<td style="padding-left: 20px;">
{if $order_docId == '' && $config_CreaOrdine eq 1}
<button type="submit" name="submit_order" id="submit_order" class="btn btn-primary" onclick={saveDocument}>Salva Ordine</button>
{/if}
</td>
<td style="padding-left: 20px;">
{if $invoice_docId == '' && !$config_CreaFattura eq 0}
<button type="submit" name="submit_invoice" id="submit_invoice" class="btn btn-primary" onclick={saveDocument}">Salva Fattura</button>
{/if}
</td>
</tr>
</tbody>
</table>
</div>
At last in my php file I define the function "smartyDocument". I wish a slight different behaviour of it, based on the button id. Anyone knows how I can I get the button id and pass it to "smartyDocument" function? I hope is all clear, thx
You cannot use any Smarty commands after loading the page. You can use the Javascript function instead.
Smarty is a server-side engine and the output is sent to the browser after processing, which is quite static.
You have to have a Javascript function to save your document by Ajax:
send your data to PHP
save data
return success or fail message

Vuejs2- Avoid repetition of select field options using vee-validate

Iam using vee-validate plugin for validation. In my form, there is a select field in the table. Rows will be added dynamically in the table. I don't want to select the same select(Description column) option again and again Image. Hence I want to throw an error like "Selected description already exists in a table" this using vee-validate. Kindly help me to solve this.
Here is my code:
<template>
<div>
<b-card>
<div class="panel-body" id="app">
<table class="table table-hover">
<thead>
<tr>
<th style="width: 20px;">No.</th>
<th style="width: 330px;">Description</th>
<th style="width: 130px;" class="text-right">Charges</th>
<th style="width: 130px;">Total</th>
<th style="width: 130px;"></th>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in rows" :key="row.qty">
<td>
{{ index +1 }}
</td>
<td>
<select class="form-control" v-model="row.billChgDesc" v-validate="'required|check'" :name="'billChgDesc' + index" data-vv-as="Description" #change="checkRepetation">
<option v-for="option in billChgDescOpt" v-bind:value="option.value"
:key="option.value"> {{ option.text }}
</option>
</select>
<span v-show=" errors.has('billChgDesc' + index)" class="is-danger">{{ errors.first('billChgDesc' + index) }}</span>
</td>
<td>
<input class="form-control text-right" type="text" v-model="row.charges" data-type="currency" v-validate="'required'" :name="'charges' + index" data-vv-as="Charges" >
<span v-show=" errors.has('charges' + index)" class="is-danger">{{ errors.first('charges' + index) }}</span>
<td>
<input class="form-control text-right" :value="row.qty * row.charges" number readonly />
<input type="hidden" :value="row.qty * row.charges * row.tax / 100" number/>
</td>
<td>
<button class="btn btn-primary btn-sm" #click="addRow(index)"><i class="fa fa-plus"></i></button>
<button class="btn btn-danger btn-sm" #click="removeRow(index)"><i class="fa fa-minus"></i></button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="3" class="text-right">TOTAL</td>
<td colspan="1" class="text-right"><input class="form-control text-right" v-model="delivery" number/></td>
<td></td>
</tr>
</tfoot>
</table>
</div>
</b-card>
</div>
</template>
<script>
import Vue from 'vue'
import accounting from 'accounting'
export default {
data: function () {
return {
billChgDescOpt: [
{ value: '', text: 'Select' },
{ value: 'M', text: 'Maintenance Fee'},
{ value: 'W', text: 'Water Charges'},
{ value: 'P', text: 'Penalty Fee'},
],
rows: [
{qty: 5, billChgDesc: '', charges: 55.20, tax: 10},
{qty: 19, billChgDesc: '', charges: 1255.20, tax: 20},
],
grandtotal: 0,
delivery: 40,
selectArr:[]
}
},
methods: {
addRow: function (index) {
try {
this.rows.splice(index + 1, 0, {});
} catch(e)
{
console.log(e);
}
},
removeRow: function (index) {
this.rows.splice(index, 1);
},
checkRepetation:function(){
this.$validator.extend('check', {
getMessage: field => '* Slected ' + field + ' already exists',
validate: function(value){
selectArr.push(value);
}
})
}
}
}
</script>
<style lang="scss" scoped>
.is-danger{
color: RED;
}
</style>
Thanks in advance.
You're on the right track, but a couple changes need to be made. When you call this.$validator.extend, that only needs to be done once - when your component is created. It attaches the check method to the validator, so then every time you have the attribute v-validate="'required|check'" in your HTML, it will run that check method.
In your check validator, you need to answer the question "is this value already selected". The answer is to go through the this.rows and see if any of them have the same billChgDesc property. Because this is in Vue, by the time the validator gets run, the row in question already does have that value, so you want to check if MORE than one row have that value. So, something like this:
mounted() {
var self = this;
this.$validator.extend('check', {
getMessage: field => '* Selected ' + field + ' already exists',
validate: function(value){
return (self.rows.filter(function(v){
return v.billChgDesc == value;
}).length <= 1);
}
});
}
This validator returns true if only one item has the given value. I'm using the built-in filter method of Array (see docs).
You can see an example of this all working here: https://jsfiddle.net/ryleyb/f9q50wx4/1/

How to set header value in kendo grid row template

I am using jquery kendo grid in my project where i used row template to show three column in one row. Below is the code:
<table id="grid" style="width:100%">
<thead style="display:none">
<tr>
<th>
Details
</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="3"></td>
</tr>
<tr>
<td>
</td>
</tr>
</tbody>
</table>
<script id="rowTemplate" type="text/x-kendo-tmpl">
<div>
<span class="name" style="font-size:medium">#: FirstValue #</span>
<span class="name" style="font-size:medium">#: SecondValue #</span>
</div>
<tr>
<td style="width:30%">
#: GetName #
<span class="name" style="font-size:14px; color:green">#: Designation #</span>
<span class="name" style="font-family:Arial; font-size:small">#: Company #</span>
</td>
</tr>
</script>
in the above code i am just passing my model data it's working fine but when i added one div which have value firstName and LastName so it is also repeating with this data but i want to to show separately.How do i show it separately so that it should not repeat with grid.
there is one problem in your html template.
Please replace '#' with 'Javascript:void(0)'.
Error:- #: GetName #
Fix:- #: GetName #
Hope that's work for you.
http://jsfiddle.net/parthiv89/t0w3ht6m/1/
if you like then don't forget to like.
I got solution by own, Firstly i changed code in my schema like this:
schema: {
parse: function (data) {
var items = [];
for (var i = 0; i < data.data.length; i++) {
if (data.data[i].CorrectValue != null && data.data[i].SearchValue != null) {
$("#spnSR")[i].innerHTML = "<b>"+"Get results for this text: "+"</b>"+data.data[i].CorrectValue;
$("#spnSV")[i].innerHTML = "<b>" + "Searched for this text: " +"</b>" + data.data[i].SearchValue;
}
}
var product = {
data: data.data,
total: data.total
};
items.push(product);
return (items[0].data);
},
}
Then in html i used two span to show this value which is there in for loop.
and it's working fine for me.
Thanks everyone.

Can datatables sort a column with an input field?

I am trying to make datatables sort my columns. The first column works okay as it's a simple number. However the next column is an input field. When I try to make that sort then nothing happens.
<table width="100%" cellspacing="0" class="table sortable no-margin">
<thead>
<tr>
<th scope="col" class="sorting" style="width: 57px;">
<span class="column-sort">
</span>
ID
</th>
<th scope="col" class="sorting_desc" style="width: 94px;">
<span class="column-sort">
</span>
Order
</th>
</tr>
</thead>
<tbody>
<tr id="row_20" class="odd">
<td id="refKey_20" style="text-align:center;" class="">
1Y
</td>
<td class=" sorting_1">
<input type="text" value="160" size="3" name="item.Order"
maxlength="3" id="Order_20" >
</td>
</tr>
<tr id="row_19" class="even">
<td id="refKey_19" style="text-align:center;" class="">
1X
</td>
<td class=" sorting_1">
<input type="text" value="150" size="3" name="item.Order"
maxlength="3" id="Order_19" >
</td>
</tr>
</tbody>
</table>
Is there some way that I can get datatables to sort input fields?
The easiest way is to add a hidden span inside columns <span style="visibility:hidden">value of the input</span>
You should look at this example that explains how to do sorting on input fields. Basically you declare a sorting function
/* Create an array with the values of all the input boxes in a column */
$.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn )
{
var aData = [];
$( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
aData.push( this.value );
} );
return aData;
}
And then tell to your table to use that
$('#example').dataTable( {
"aoColumns": [
null,
{ "sSortDataType": "dom-text" }
]
} );
or wit aoColumnDefs
$('#example').dataTable( {
"aoColumnDefs": [{ "sSortDataType": "dom-text" , aTarget: "yourclass"}]
} );
For versions of Datatables 1.10+ the names of some option variables have been changed and a new API introduced. Documentation here: http://datatables.net/examples/plug-ins/dom_sort.html.
Here is a working version of the above accepted answer in 1.10+:
$(document).ready(function () {
var table = $('#example').DataTable({
"columnDefs": [
{
"orderDataType": "dom-input",
"targets": 0, // Just the first column
},
],
});
});
The custom sort function:
$.fn.dataTable.ext.order['dom-input'] = function (settings, col) {
return this.api().column(col, { order: 'index' }).nodes().map(function (td, i) {
return $('input', td).val();
});
}
jQuery.fn.dataTableExt.oSort['textbox-asc'] = function (a, b) {
var vala = $('#' + $(a).filter('input').attr('id')).val().toLowerCase();
var valb = $('#' + $(b).filter('input').attr('id')).val().toLowerCase();
if (vala === '')
return 1;
if (valb === '')
return -1;
return vala < valb ? -1 : vala > valb ? 1 : 0;
};
jQuery.fn.dataTableExt.oSort['textbox-desc'] = function (a, b) {
var vala = $('#' + $(a).filter('input').attr('id')).val().toLowerCase();
var valb = $('#' + $(b).filter('input').attr('id')).val().toLowerCase();
if (vala === '')
return 1;
if (valb === '')
return -1;
return vala < valb ? 1 : vala > valb ? -1 : 0;
};
then use it like this
$(datatable).dataTable({
"iDisplayLength": 50,
"bLengthChange": false,
"bPaginate": false,
"columns": [
null, { "sType": "textbox" }
],
});
If you decide to use the columns option where you are rending information from a JSON file you can easily add a hidden span on your render property. It appears as though DataTables looks for text to order and if it cannot find any, it will break. The example at https://datatables.net/examples/plug-ins/dom_sort.html uses a table that has already been rendered. Here is an example using an API:
...columns([{
"data": "receivedDate",
"render": function (data, type, row, meta)
{
if (data == "null")
{
return "<input type='text' id='datepicker_" + meta.row + "' class='datepicker form-control' /><span class='hidden'><span>";
}
else
{
return "<input type='text' id='datepicker_" + meta.row + "' class='datepicker form-control' value='" + moment(data).format("MM/DD/YYYY") + "'/><span class='hidden'>" + moment(data).format('MM/ DD / YYYY') + "</span>";
}
}
}]);
Set an invisible div with the value before the input field.
<tbody>
<tr id="row_20" class="odd">
<td id="refKey_20" style="text-align:center;" class="">
1Y
</td>
<td class=" sorting_1">
<div style="display:none;">160</div>
<input type="text" value="160" size="3" name="item.Order"
maxlength="3" id="Order_20" >
</td>
</tr>
<tr id="row_19" class="even">
<td id="refKey_19" style="text-align:center;" class="">
1X
</td>
<td class=" sorting_1">
<div style="display:none;">150</div>
<input type="text" value="150" size="3" name="item.Order"
maxlength="3" id="Order_19" >
</td>
</tr>
</tbody>