I have a page with a jQuery Datatable being from Ajax, and drawn with the npm treeGrid plugin. The table is drawn fine, but i'm trying to catch the end of the table loading to do some stuff (get additional data to be ready when the tree is expanded). The init.dt event or the initComplete option are fired before the table is drawn. If i put an alert in the event it is shown after the table top and bottom are drawn but before the data is rendered. And if i try to access the table data it is undefined.
Important: I get the same behavior if I remove the treeGrid object from the DataTable options. I even removed the treeGrid javascript...
So my question is: how can i have code run when everything is really ready?
Below are two implementations of the Datatble, with either init.dt or initComplete. I am also adding the columns object. Below are two screenshots of the alert and then the table drawn.
$(document).ready(function () {
$('#mainTable')
.on('init.dt', function () {
alert('Table initialisation complete')
})
.DataTable({
"ajax": '/API/RRate',
'treeGrid': {
'left': 20,
'expandIcon': '<span>+</span>',
'collapseIcon': '<span>-</span>'
},
"columns": columns
});
});
$(document).ready(function () {
$('#mainTable')
.DataTable({
"ajax": '/API/RRate',
'treeGrid': {
'left': 20,
'expandIcon': '<span>+</span>',
'collapseIcon': '<span>-</span>'
},
"columns": columns,
"initComplete": function (settings, json) {
alert('Table initialisation complete')
}
});
});
var columns = [
{
title: '',
target: 0,
className: 'treegrid-control',
data: function (item) {
if (item.children) {
return '<span>+</span>';
}
return '';
}
},
{
title: 'Name',
target: 1,
data: function (item) {
return item.name;
}
},
{
title: 'HeadCount',
target: 2,
data: function (item) {
return item.headCount;
}
},
{
title: 'Responded',
target: 3,
data: function (item) {
return item.responded;
}
},
{
title: 'Percentage',
target: 4,
data: function (item) {
return item.percentage;
}
},
{
title: 'InProcess',
target: 5,
data: function (item) {
return item.inProcess;
}
},
];
OK, i found how to do this:
function AfterLoad()
{
table.rows().each(function () {
console.log(this.cells(0));
var rowData = this.data();
console.log(rowData[0]);
});
}
$(document).ready(function () {
table = $('#mainTable')
.DataTable({
"ajax": '/API/RRate',
'treeGrid': {
'left': 20,
'expandIcon': '<span>+</span>',
'collapseIcon': '<span>-</span>'
},
"columns": columns,
"initComplete": function (settings, json) {
AfterLoad();
}
});
});
Related
I found a TreeGrid extension for DataTables:
https://homfen.github.io/dataTables.treeGrid.js/
but instead of the name I would like to add a column between name and position and place a checkbox here.
However when I do this e.g.:
var columns = [
{
title: '',
target: 0,
className: 'treegrid-control',
data: function (item) {
if (item.children) {
return '<span>+<\/span>';
}
return '';
}
},
{
title: 'Name',
target: 1,
data: function (item) {
return item.name;
}
},
{
defaultContent: '',
target: 2,
className: 'select-checkbox',
function(item) {
return item;
}
},
{
title: 'Position',
target: 3,
data: function (item) {
return item.position;
}
},
{
title: 'Office',
target: 4,
data: function (item) {
return item.office;
}
},
{
title: 'Extn.',
target: 5,
data: function (item) {
return item.extn;
}
},
{
title: 'Start date',
target: 6,
data: function (item) {
return item.start;
}
},
{
title: 'Salary',
target:7,
data: function (item) {
return item.salary;
}
}
];
I get an extra column but when checking the parent does not select all underlying children rows.
Anyone have an idea how to establish this?
Edit: updated the columns definition.
When I add a button to read the selected values e.g.:
dom: 'Bfrtip',
select:true,
buttons: [
{
text: 'Alert selected',
action: function(e, dt, node, config) {
var data = table.rows({
selected: true
}).data().toArray();
var i;
var text = new Array();
for (i = 0; i < data.length; i++) {
text.push(data[i].name);
}
alert("you selected: " + text.join(",") );
console.log("text---" + text.join(","));
}
}
]
the table starts to behave oddly for example: the selection of underlying children stops.
So I wanted to see if I can get some guidance from the community if there is a better way to approach this:
So I have the following vue.js app:
new Vue({
name: 'o365-edit-modal-wrapper',
el: '#o365-modal-edit-wrapper',
data: function() {
const default_apps = [
{
'post_title': 'Excel',
}, {
'post_title': 'Word',
}, {
'post_title': 'SharePoint',
}];
return {
available_list: [],
selected_list: default_apps.map(function(name, index) {
return { name: name.post_title, order: index + 1, fixed: false };
}),
}
},
computed: {
dragOptions() {
// Pass in additional <draggable> options inside the return for both lists.
return {
tag: 'div',
group: 'o365apps',
disabled: !this.editable,
ghostClass: "ghost",
};
},
},
});
The selected_list returns the following items:
I was told that it's bad practice to do array mapping inside the data return, but to instead map inside the computed call - Could someone lead me in the right direction and just see if my code makes sense?
I tried defining an empty array as shown below:
return {
available_list: [],
selected_list:[],
}
& then inside the computed property, I tried accessing it using the following return but wasn't getting any data back:
selected_list() {
return this.default_apps.map(function(name, index) {
return { name: name.post_title, order: index + 1, fixed: false };
});
},
All help is appreciated - Thanks a bunch!
your are almost there except for a few details:
It's ok to map data inside data as long as you put them inside the return object literal data() { return { default_apps: [] } }.
Once default_apps is inside the return object of data, you can access the data inside of it from a computed property using the this keyword: this.default_apps.map()...
new Vue({
name: 'o365-edit-modal-wrapper',
el: '#o365-modal-edit-wrapper',
data: function() {
return {
default_apps: [
{ post_title: 'Excel' },
{ post_title: 'Word' },
{ post_title: 'SharePoint'}
],
available_list: [],
}
},
computed: {
selected_list() {
return this.default_apps.map(function(name, index) {
return { name: name.post_title, order: index + 1, fixed: false };
});
},
dragOptions() {
// Pass in additional <draggable> options inside the return for both lists.
return {
tag: 'div',
group: 'o365apps',
disabled: !this.editable,
ghostClass: "ghost",
};
},
},
});
I am new to angular 7 and want to implement datatable in angular 7.
I displayed data from api, and I triggered event from the table cell.
now I want to get data from the cell. but I get the data is null.
This is a component to display data from rest api.
ngOnInit() {
this.dataService.getMeterReading().subscribe(tourData => {
this.dtOptions = {
bLengthChange : false,
bInfo: false,
data: tourData,
columns: [
{
title: 'Unit',
data: 'UnitID'
},
{
title: 'Latitude',
data: 'DeviceID'
},
{
title: 'Logitude',
data: 'DeviceID'
},
{
title: 'Remarks',
data: 'DeviceID'
},
{
title: 'Image',
data: 'Image',
render: (data) => {
return data ? `<i class="fa fa-picture-o ImageMeterReading" data-blob="${data.data}" aria-hidden="true"></i>` : '';
}
}
]
};
$(document).on('click', 'i.ImageMeterReading', ($event) => {
let blob = $($event).data('blob');
});
this.dataTable = $(this.table.nativeElement);
this.dataTable.DataTable(this.dtOptions);
this.loading = false;
}
}
I expect to get BLOB data from the table cell.
but the actual output is null now.
I'm trying to implement a datatable with mdbootstrap in vue.js.
I would like to update table data on events and when initialized but it does not work.
Template;
<div class="col-md-12">
<mdb-datatable
:data="data"
striped
bordered
/>
</div>
Script;
import { mdbDatatable } from 'mdbvue';
export default {
name: 'userManagement',
components: {
mdbDatatable
},
data() {
return {
className:"",
classList: [],
data: {
columns: [
{
label: 'Name',
field: 'className',
sort: 'asc'
}, {
label: 'ID',
field: 'id',
sort: 'asc'
}
],
rows: [
{
className: 'Tiger Nixon',
id:1
},
{
className: 'Garrett Winters',
id:2
}
]
}
}
},
methods: {
getClassList(){
var _this = this;
this.$axios.get('my_url/admin/classes').then(function (response) {
if (response.status === 200) {
_this.data.rows = [];
response.data.forEach(function (obj) {
let item = {
className: obj.className,
id: obj.id
};
_this.data.rows.push(item);
});
}
}).catch(function (err) {
alert("" + err);
});
}
},
mounted(){
this.getClassList();
},
It always shows default values, I check the data rows from console the value seems to be updated but no change on the datatable.
Any help would be appreciated.
We've found the solution for Your issue.
The new code is available here: https://mdbootstrap.com/docs/vue/tables/datatables/#external-api
Also to make sure the data is reactive it's necessary to add the following code to the Datatable component in our package:
watch: {
data(newVal) {
this.columns = newVal.columns;
},
(...)
}
It will be fixed in the next MDB Vue release.
I installed mdbvue 5.5.0 which includes the change that mikolaj described. This caused the table columns to update when changed but in order to get the rows to update too I had to add to the watch method in Datatable.vue as follows:
watch: {
data(newVal) {
this.columns = newVal.columns;
this.rows = newVal.rows;
},
I'm new to vue and have followed their 'custom directive' at http://vuejs.org/examples/select2.html.
This works well when only selecting one item, but when you're selecting multiple items it only passes the first one. I need it to pass all values selected.
I have a jsfiddle set up displaying the code which is available here.
https://jsfiddle.net/f3kd6f14/1/
The directive is as below;
Vue.directive('select', {
twoWay: true,
priority: 1000,
params: ['options'],
bind: function() {
var self = this
$(this.el)
.select2({
data: this.params.options
})
.on('change', function() {
self.set(this.value)
})
},
update: function(value) {
$(this.el).val(value).trigger('change')
},
unbind: function() {
$(this.el).off().select2('destroy')
}
Any help would be appreciated.
this.value doesn't work like you expect when Select2 is in multiple value mode (more info here: Get Selected value from Multi-Value Select Boxes by jquery-select2?).
Try this (working fiddle here: https://jsfiddle.net/02rafh8p/):
Vue.directive('select', {
twoWay: true,
priority: 1000,
params: ['options'],
bind: function() {
var self = this
$(this.el)
.select2({
data: this.params.options
})
.on('change', function() {
self.set($(self.el).val()) // Don't use this.value
})
},
update: function(value) {
$(this.el).val(value).trigger('change')
},
unbind: function() {
$(this.el).off().select2('destroy')
}
})
var vm = new Vue({
el: '#el',
data: {
selected: [], // Result is an array of values.
roles : [
{ id: 1, text: 'hello' },
{ id: 2, text: 'what' }
]
}
})
In Vue 2, to get all select2 values onchange:
Change this:
.on('change', function () {
self.$emit('input', this.value); // Don't use this.value
});
To this:
.on('change', function () {
self.$emit('input', $(this).val());
});