I'm having problems putting some actions buttons in mdbootstrap datatable
I'm following their example but without fetching data and i need to fetch data from my database
The records are present but the buttons no and i need them to get the results i need
This is my javascript code
$(document).ready(function () {
const customDatatable = document.getElementById('datatable-custom');
const columns = [
{ label: 'ID', field: 'idAtividade', width: 25 },
{ label: 'Atividade', field: 'atividade', width: 175 },
{ label: 'Projeto', field: 'nome', width: 150 },
{ label: 'Aulas', field: 'haveClasses', width: 25 },
{ label: 'Orçamento', field: 'orcamento', width: 25 },
{ label: 'Data', field: 'dataAtividade', width: 100 },
{ label: 'Hora', field: 'hora', width: 50 },
{ label: 'Local', field: 'local', width: 150 },
{ label:'Opções', field: '',sort: false }
];
const rows = [
fetch('./controllers/Atividades.php?type=listar')
.then((data) => data.json())
.then((data) => {
const parser = new DataParser('datatable', {
rows: {start: 30, end: 100},
keys: columns.map((column) => column.field),
});
const { rows } = parser.parse(data);
datatableInstance.update({ rows }, { loading: false });
}),
];
const setActions = () => {
document.getElementsByClassName('call-btn').forEach(btn => {
btn.addEventListener('click', () => {
console.log(`call ${btn.attributes['data-mdb-number'].value}`)
})
})
document.getElementsByClassName('message-btn').forEach(btn => {
btn.addEventListener('click', () => {
console.log(`send a message to ${btn.attributes['data-mdb-email'].value}`)
})
})
};
customDatatable.addEventListener('render.mdb.datatable', setActions);
const datatableInstance = new mdb.Datatable(customDatatable,
{ columns },{
rows: [
rows
].map((row) => {
console.log("aqui");
return {
...row,
contact: `<button class="call-btn btn btn-outline-primary btn-floating btn-sm" data-mdb-number="${row.phone}"><i class="fa fa-phone"></i></button>
<button class="message-btn btn ms-2 btn-primary btn-floating btn-sm" data-mdb-email="${row.email}"><i class="fa fa-envelope"></i></button>`,
};
}),
},
{ hover: true });
});
And this is what i get
Image of my datatable
i think you're doing this with wrong way, you basically can use datatable feature to solve your problem. you want to fetch data from database and draw the data to the table with custom button in it, isnt it?
alright here is how i do it
1.Lets make your table, i prefer to define my initial table directly by html
<table id="datatable-custom" class="table">
<thead>
<th>ID</th>
<th>Atividade</th>
<th>Projeto</th>
<th>Aulas</>
<th>Orçamento</th>
<th>Data</th>
<th>Hora</th>
<th>Local</th>
<th>Opções</th>
</thead>
<tbody></tbody>
</table>
just leave blank
2.initialize the table
const customDatatable = document.getElementById('datatable-custom')
customDatatable.DataTable({
ordering: false,
responsive: true,
autoWidth: false,
rowId: 'key',
ajax: {
url:'http://yourapi.com'
dataSrc: ''
},
columns: [
{data:'your_object_data_key'}
...,
{
data: function(row){
return `<button data-id="${row.your_key_id}">your custom button</button>`
}
}
columnDefs: [{
targets: 8,
data: null,
defaultContent: `<button class="btn btn-info"><i class="fas fa-edit"></i></button>`
}],
})
Note :
if you want to pass your data to the button for each row data, then the data: function(row){...} can be used for that, the data will be passed through the ${row.key},
but if you don't pass any data to the button you can use the columnDefs and delete the part of data: function(row){...}. the targets: 8 that i assume that you will put the button at the column "Opções" since the column index is 8. you can define yourself where this button will be put
The dataSrc is defining the object that will be used to the table, if your object data cantains ex.
Example response data from your database api
{
msg_status:true,
msg_body:[{
key1:"data",
key2:"data"
}]
}
So you can use dataSrc: "msg_body"
Let me know if this works for you
Related
I'm trying to populate possible dropdown options on vue good table. The idea is that I conduct an API call to the server to bring back what values can possibly go into the drop down and I'm trying to assign it to the column filter. However, I can't seem to get it to work.
<vue-good-table
:paginationOptions="paginationOptions"
:sort-options="sortOptions"
:isLoading.sync="isTableLoading"
:rows="rows"
:columns="columns"
:lineNumbers="true"
mode="remote"
:totalRows="totalRecords"
#on-row-click="onRowClick"
#on-page-change="onPageChange"
#on-sort-change="onSortChange"
#on-column-filter="onColumnFilter"
#on-per-page-change="onPerPageChange"
#on-search="onSearch"
:search-options="{
enabled: true
}"
styleClass="vgt-table striped bordered"
ref="table"
>
Fairly standard vgt set up.
columns: [
{
label: 'some column',
field: 'column1'
},
{
label: 'Customer',
field: 'customerName',
filterOptions: {
enabled: true,
placeholder: 'All',
filterDropdownItems: Object.values(this.customers)
}
},
{
label: 'other columns',
field: 'column234'
}
]
and the API call
methods: {
async load () {
await this.getTableOptions()
},
async getTableOptions () {
try {
var response = await axios.get(APICallUrl)
this.customers= []
for (var i = 0; i < response.data.customers.length; i++) {
this.customers.push({ value: response.data.customers[i].customerId, text: response.data.customers[i].customerName})
}
} catch (e) {
console.log('e', e)
}
}
The only thing that I thought of is that the table has finished rendering before the load method is complete. However just creating a static object in my data and assigning it to a filterDropDownItems yielded no better results. The result whenever I try to set it to an object is that the box is a type-in box rather than a dropdown.
You can make the table update after it's rendered by making columns a computed property. The other problem you have is this.customers is an Array but Object.values() expects an Object. You could use the Array.map function instead
this.customers.map(c => c.value)
Although according to the VueGoodTable docs an array of objects like you have should work just fine
computed: {
columns() {
return [
{
label: 'some column',
field: 'column1'
},
{
label: 'Customer',
field: 'customerName',
filterOptions: {
enabled: true,
placeholder: 'All',
filterDropdownItems: this.customers
}
},
{
label: 'other columns',
field: 'column234'
}
];
}
}
I have changed the default font to a font that supports arabic
The words supposed to be shown this way:
تقارير حركة الرسائل
But they are shown as
الرسائل حركة تقارير
function processDoc(doc) {
// https://pdfmake.github.io/docs/fonts/custom-fonts-client-side/
pdfMake.fonts = {
Roboto: {
normal: 'Roboto-Regular.ttf',
bold: 'Roboto-Medium.ttf',
italics: 'Roboto-Italic.ttf',
bolditalics: 'Roboto-MediumItalic.ttf'
},
scheherazade: {
normal: 'Scheherazade-Regular.ttf',
bold: 'Scheherazade-Regular.ttf',
italics: 'Scheherazade-Regular.ttf',
bolditalics: 'Scheherazade-Regular.ttf'
}
};
// modify the PDF to use a different default font:
doc.defaultStyle.font = "scheherazade";
}
$(function () {
var table = $('.data-table').DataTable({
processing: true,
serverSide: true,
ajax: {
url: "{{ route('messaage_movements.index') }}",
"method": "GET",
data: function (d) {
d.search = $('input[type="search"]').val()
}
},
dom: 'Bfrtip',
buttons: [
// {
// extend: 'pdfHtml5',
// text: 'PDF',
// } ,
'copyHtml5',
'excelHtml5',
'csvHtml5',
'print',
{
extend: 'pdfHtml5',
// download: 'open',
title: '{{__('messages.messaage_movements')}}',
customize: function ( doc ) {
processDoc(doc);
doc.content.splice( 1, 0, {
margin: [ 0, 0, 0, 12 ],
alignment: 'right',
} );
},
}
],
columns: [
{data: 'id', name: 'id'},
{data: 'message', name: 'message'},
{data: 'user_id', name: 'user_id'},
{data: 'number_massages', name: 'number_massages'},
{data: 'status', name: 'status'},
{data: 'reason', name: 'reason'},
{data: 'date_sent', name: 'date_sent'},
{
data: 'action',
name: 'action',
orderable: true,
`enter code here` searchable: true
},
]
});
});
I have followed a code like that but turned it into arabic
I don't know where to put the direction="rtl" in the code cause It's not a visible html tag
enter link description here
-----edit
The changes I've made above solved the problem of the title and the rows but not the thead.
customize: function ( doc ) {
processDoc(doc);
doc.content[0]['text'] = doc.content[0]['text'].split(' ').reverse().join(' ');
},
}
],
columns: [
{data: 'id', name: 'id'},
{data: 'message', name: 'message',targets: '_all',render: function(data, type, row) {
if (type === 'myExport') {
return data.split(' ').reverse().join(' ');
}
console.log(data);
return data;
}},
This library doesn't support rtl very well.. but you could fix this issues in table body using "render" function in columns option to reverse the content..
the problem is with your table head, because you can't customize table header content..
but I figured out a trick to solve this issue..
the idea is to create two table headers.. one reversed and hidden from the html page.. while the other is not reversed and shown in html, the library will only detect the reversed one and display it in the pdf file
to apply this just add this code to your js file..
let thead = document.getElementsByTagName('thead')[0].children[0]
const reversedHead = thead.cloneNode(true)
thead.parentNode.appendChild(reversedHead)
let headCells = reversedHead.children
Object.keys(headCells).forEach(i=>{
headCells[i].textContent = headCells[i].textContent.split(' ').reverse().join(' ')
})
reversedHead.setAttribute('hidden',"")
In my code, I am using AG-Grid with the master detail property to display some data. The code doesn't get any errors and the master row has records, but when I expand the detail, not 1 row is present even though in the network, params.data has values. My code is below. What am I doing wrong, and how should I fix it?
constructor(
private _reportService: ReportService,
) {
this._reportService
.getAllSupplierProductList()
.subscribe((response: any) => {
this.rowData = response;
});
}
public detailCellRendererParams: any = {
detailGridOptions: {
columnDefs: [
{ headerName: 'Ürün Kodu', field: 'StockIntegrationCode' },
{ headerName: 'Ürün Adı', field: 'ProductName' },
{ headerName: 'Ürün Kategorisi', field: 'CategoryName' },
],
defaultColDef: {
flex: 1,
filter: 'agTextColumnFilter',
resizable: true,
sortable: true,
floatingFilter: true,
},
},
getDetailRowData: (params) => {
params.successCallback(params.data.StockIntegrationCode && params.data.ProductName && params.data.CategoryName);
},
} as IDetailCellRendererParams;
rowData: Observable<IReportRow[]>;
onFirstDataRendered(params: FirstDataRenderedEvent) {
// arbitrarily expand a row for presentational purposes
setTimeout(function () {
params.api.getDisplayedRowAtIndex(1)!.setExpanded(true);
}, 0);
}
onGridReady(params: GridReadyEvent) {
}
In the getDetailRowData function, you're given params.data, which is the data of the master row. You should obtain details and pass it to the params.successCallback function like this:
getDetailRowData: (params) => {
this._reportService
.getProductList(params.data.SupplierId)
.subscribe(products => {
params.successCallback(products);
});
}
I'm using an ag-grid to populate list records(rows) in a table. I'm trying to delete a record from the grid-table when the user clicks a "Delete" button in one of the cell. I'm able to add the "Delete" button to the grid but how can I capture the index of the clicked "Delete" in the table and remove that row.
table's grid options are defined in file specials.Vue
*function setGridOptions() {
this.gridOptions = {
columnDefs: [{
headerName: 'Model',
field: 'scModel',
editable: params => this.isCellEditable(params),
newValueHandler: this.NewValueHandler,
width: 120,
},
{
headerName: 'Delete ',
width:50,
field: 'delete',
cellRenderer: deleteRecordCellRender,
},
],
rowData: this.getInitialRowData(),
headerHeight: 36,
rowHeight: 28,
suppressMovableColumns: true,
suppressMenuMainPanel: true,
suppressMenuFilterPanel: true,
suppressMenuColumnPanel: true,
suppressContextMenu: true,
singleClickEdit: true,
rowSelection: 'single',
};
}*
The 'Delete' column rendered from 'deleteRecordCellRender' defined in javascript file ag-gridFunction.js
*export function deleteSpecialRecordCellRender() {}
deleteSpecialRecordCellRender.prototype.init = deleteSpecialRecordCellRenderInit;
deleteSpecialRecordCellRender.prototype.getGui = deleteSpecialRecordCellRenderGetGui;
function deleteSpecialRecordCellRenderGetGui() {
return this.eGui;
}
function deleteSpecialRecordCellRenderInit() {
console.log('deleteSpecialRecordCellRenderInit this: ', this);
this.eGui = `<button class="btn btn-default btn-sm delete-row-button" rel="">Delete</a>`;
}*
delete-row-button function defined in specials.Vue file is
$('.delete-row-button').on('click', () => {
console.log('made it');
console.log('scope: ', this);
console.log('clicked row',$scope.gridOptions.api.getSelectedRows())
});
But It's not getting the selectedRow due to a scope issue. How do I get the selected row index and delete after ?
I'm using Quasar Framework with VueJS. I have a Data Table component that allows single item selection. The Data Table data is automatically updated every 5 seconds through websockets events. If I have an item selected, every time the Data Table data is updated, that item gets deselected, and I would like to persist the item selection after the data is updated.
Is there a way to accomplish this? I was thinking in two different approachs, but I have no idea how to do it, at least not from the documentation:
access directly the Data Table selected item
handle an event fired when an item is selected
In both cases the main idea would be to save the selection in a store, an restore the selection when the Data Table items update is done.
<template>
<q-layout>
<!-- Main block start-->
<div class="scroll" style="width: 100%">
<div class="layout-padding">
<div class="row" style="margin-top: 30px;">
<q-data-table :data="dataTableData" :config="config" :columns="columns" #refresh="refresh">
</q-data-table>
</div>
</div>
</div>
<!-- Man block end-->
</q-layout>
</template>
<script>
export default {
sockets:{
connect: function(){
console.log('socket connected')
},
info: function(data){
console.log('sockets: info',data)
//This is where I should get the current selected item if exists
this.dataTableData = data;
//This is where I should restore the selected item
}
},
methods: {
getInfo: function(val){
this.$socket.emit('getInfo', val);
},
refresh (done) {
this.$socket.emit('getInfo');
done();
}
},
created: function(){
this.getInfo()
},
data: function () {
return {
dataTableData: [],
config: {
title: 'My Data Table',
refresh: true,
columnPicker: false,
leftStickyColumns: 0,
rightStickyColumns: 0,
rowHeight: '50px',
responsive: true,
selection: 'single',
messages: {
noData: '<i>warning</i> No data available to show.'
}
},
columns: [
{ label: 'Name', field: 'name', width: '200px', sort: true },
{ label: 'Size', field: 'size', width: '50px', sort: true },
{ label: 'Status', field: 'status', width: '50px', sort: true },
{ label: 'Progress', field: 'progress', width: '150px', sort: false },
{ label: 'Speed', field: 'speed', width: '50px', sort: false },
{ label: 'ETA', field: 'eta', width: '50px', sort: false }
],
pagination: false,
rowHeight: 50,
bodyHeightProp: 'auto',
bodyHeight: 'auto'
}
},
watch: {
}
}
</script>
UPDATE
As far as I can see, they're already working in this enenhancement for the Quasar-Framework v0.14 =)