Datatables date sort vs date display - javascript

I am using Datatables to display a table and I am pulling a list of datestimes from a MySQL database. These date times are not standard dates and look like this:
12/30/19 # 04:17 pm
How can I sort these accurately with Datatables?
Here is my code:
getRes(function (result) { // APPLIED CALLBACK
$('#resdatatable').DataTable({
data: result, // YOUR RESULT
order: [[ 0, "desc" ]],
autoWidth: false,
responsive: true,
columns: [
{ data: 'id', title: 'ID' },
{ data: 'bookingdatetime', title: 'Booking Date' },
{ data: 'name', title: 'Name' },
{ data: 'class', title: 'Class' },
{ data: 'pickupdatetime', title: 'Pick up' },
{ data: 'duration', title: 'Duration' },
{ data: 'dropdatetime', title: 'Drop off' },
{ data: 'age', title: 'Age' },
{ data: 'coverage', title: 'Coverage' },
{ data: 'quote', title: 'Quote' },
{
data: 'status',
title: 'Status',
render: function(data, type, row) {
let isKnown = statusList.filter(function(k) { return k.id === data; }).length > 0;
if (isKnown) {
return $('<select id="resstatus'+row.id+'" onchange="changeResStatus('+row.id+')" data-previousvalue="'+row.status+'">', {
id: 'resstatus-' + row.id, // custom id
value: data
}).append(statusList.map(function(knownStatus) {
let $option = $('<option>', {
text: knownStatus.text,
value: knownStatus.id
});
if (row.status === knownStatus.id) {
$option.attr('selected', 'selected');
}
return $option;
})).on('change', function() {
changeresstatus(row.id); // Call change with row ID
}).prop('outerHTML');
} else {
return data;
}
}
}
]
});
});
/**
* jQuery plugin to convert text in a cell to a dropdown
*/
(function($) {
$.fn.createDropDown = function(items) {
let oldTxt = this.text();
let isKnown = items.filter(function(k) { return k.id === oldTxt; }).length > 0;
if (isKnown) {
this.empty().append($('<select>').append(items.map(function(item) {
let $option = $('<option>', {
text: item.text,
value: item.id
});
if (item.id === oldTxt) {
$option.attr('selected', 'selected');
}
return $option;
})));
}
return this;
};
})(jQuery);
// If you remove the renderer above and change this to true,
// you can call this, but it will run once...
if (false) {
$('#resdatatable > tbody tr').each(function(i, tr) {
$(tr).find('td').last().createDropDown(statusList);
});
}
function getStatusList() {
return [{
id: 'Confirmed',
text: 'Confirmed'
}, {
id: 'Unconfirmed',
text: 'Unconfirmed'
}, {
id: 'Communicating',
text: 'Communicating'
}, {
id: 'Open',
text: 'Open'
}, {
id: 'Closed',
text: 'Closed'
}, {
id: 'Canceled',
text: 'Canceled'
}, {
id: 'Reallocated',
text: 'Reallocated'
}, {
id: 'No Show',
text: 'No Show'
}];
}
I need to sort bookingdatetime, pickupdatetime, dropdatetime accurately (they are currently being converted into MM/DD/YY in the PHP script)

Maybe you can prepend hidden <span> elements containing the respective unix timestamps in the cells that have dates (by manually parsing the dates). Then using such columns to sort alphabetically would practically sort time-wise.

Related

Sorting custom (currency) formatted column in backgrid

I'm using Backgridjs to display data from json object to table. I'm currently using a formatter to format string-numbers into currency. Once I did that the sorting no longer work properly as it sorting as a string rather than number. How can I enable sorting with backgrid after formatting my column ?
Backgrid support numbers, int, date/momentjs. Couldn't find extension for currency
this is my formatter class
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function(rawData) {
var re = /\-/;
if (rawData === "" || rawData == null) {
return "";
} else if (rawData.match(re)) {
return "-" + accounting.formatMoney(rawData.substr(1));
} else {
return accounting.formatMoney(rawData);
}
},
toRaw: function(formattedData) {
return formattedData;
}
}),
And this is my grid
var grid = new Backgrid.Grid({
collection: collection,
columns: [
{
name: "cost",
label: "Cost",
cell: "number",
formatter: currencyFormater
sortable: true
},
{
name: "type",
label: "Type",
cell: Backgrid.NumberCell,
sortable: true
}
]});
Example of data:
{ id: 1, cost: "150", type: 3 },
{ id: 2, cost: "12516.30", type: 2 },
{ id: 3, cost: "21400.85", type: 1 },
{ id: 4, cost: "146558.50", type: 1 },
{ id: 5, cost: "139982.75", type: 1 }
I ended up using sortValue to do specific sorting base on value. In my case I used parseFloat with the string value.
var grid = new Backgrid.Grid({
collection: collection,
columns: [
{
name: "cost",
label: "Cost",
cell: "number",
sortValue: function(model) {
return parseFloat(model.get("cost"));
},
formatter: currencyFormater
sortable: true
},
…
]});

How to read values from multiselector component

I am trying to use multiselector from EXTJS 6.5.2
This is the code that I am using to create multiselector with the values that I need
{
xtype: 'multiselector',
title: 'I caktohet:',
name: 'Caktohen[]',
bind: '{userfullname.value}',
fieldName: 'userfullname',
viewConfig: {
deferEmptyText: false,
emptyText: 'Askush i zgjedhur'
},
search: {
field: 'userfullname',
model: 'InTenders.model.UserModel',
store: {
type: 'users',
sorters: 'userfullname',
// proxy: {
// type: 'rest',
// limitParam: null,
// url: 'api/User'
// }
}
}
}
When I call form = win.down('form') records I can get all values except the multiselector values, they show like this on console.
Anyone can help me or guide me how to get the values?
Thank you.
//Code that I'm trying to get multiselector items and save them
saveTenderForm: function (button, e, eOpts) {
var userMultiSelector = Ext.getCmp('AssignedUsers'); //save assigned users
var selectedUsers = userMultiSelector.getStore().getData(); //get store and put them in array
var me = this,
win = button.up('window'),
form = win.down('form'),
// formApplyUpload = this.getFormApplyUpload(),
// var ko = win.items.items[0].items.items[0].value;
recordtenderUsers = Ext.create('InTenders.model.TenderSaveModel');
// recordtenderUsers = form.getRecord();
// record = form.getRecord(),
values = form.getValues();
// appFile = this.getApplicationFile(),
// callbacks;
recordtenderUsers.set(values);
recordtenderUsers.set('tenderUsers',selectedUsers.items);
// // me.showMask();
// if (form.isValid()) {
recordtenderUsers.save({
success: function (recordtenderUsers, operation) {
win.close();
me.hideMask();
},
failure: function (recordtenderUsers, operation) {
me.hideMask();
}
});
You can get value using multiselector.down('grid') this will return you the grid. And grid have method getSelection().
In this FIDDLE, I have created a demo. I hope this will help/guide you to achieve your requirement.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.create({
xtype: 'form',
renderTo: Ext.getBody(),
items: [{
xtype: 'multiselector',
title: 'Multi selector example',
fieldName: 'text',
viewConfig: {
deferEmptyText: false,
emptyText: 'No value selected'
},
search: {
field: 'text',
store: {
fields: [{
name: 'text',
type: 'string'
}],
data: [{
text: 'ABC'
}, {
text: 'ABC 1'
}, {
text: 'ABC 2 '
}, {
text: 'ABC 3'
}, {
text: 'ABC 4'
}]
}
}
}, {
xtype: 'button',
text: 'Get Value',
margin:15,
handler: function (btn) {
var multiselector = btn.up('form').down('multiselector');
if (multiselector.down('grid')) {
multiselector.down('grid').getSelection().forEach(rec => {
console.log(rec.get('text'));
});
}
}
}]
});
}
});

commit changes on existing records in extjs store

my issue is that I want to update existing store and show the changes on the grid.
What I'm doing to update is :
var record = store.getById(me.internalParameters.editInfo.id);
//console.log(me.InfoEditorPanel.hardwareIdField.value);
record.set('hardwareid', me.InfoEditorPanel.hardwareIdField.value);
record.set('location', me.InfoEditorPanel.locationField.value);
record.set('isActive', me.InfoEditorPanel.isActiveField.value);
record.commit();
store.load();
Here what I use to build the grid.
Utils.getPanelListGrid = function (parameters) {
if (parameters.initParameters == null)
parameters.initParameters = {};
var initParameters = parameters.initParameters;
initParameters.gridColumns = [
{ header: "ID", dataIndex: "id", flex: 1 },
{ header: "Hardware ID", dataIndex: "hardwareid", flex: 1 },
{ header: "Location", dataIndex: "location", flex: 1 },
{ header: "Active", dataIndex: "isActive", flex: 1 }
];
return new Backend.shared.MyDataGrid(parameters);
};
Ext.define(
"shared.MyDataGrid", {
extend: "Ext.grid.Panel",
xtype: "MyDataGrid",
title: "MyDataGrid - Hardcoded values",
initParameters: {
storeIdProperty: null,
},
initComponent: function () {
this.store = Ext.create('Ext.data.Store', {
storeId: 'myStore',
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'items'
}
},
fields: ['id', 'hardwareid', 'location', 'isActive'],
data: {
'items': [{
'id': '123456',
'hardwareid': "HID-159",
'location': "Bedroom",
'isActive': "No"
}, {
'id': '789456',
'hardwareid': "HID-357",
'location': "Kitchen",
'isActive': "Yes"
}, {
'id': '147852',
'hardwareid': "HID-149",
'location': "Guest-room",
'isActive': "Yes"
}
]
}
});
this.columns = this.initParameters.gridColumns;
this.listeners = {
selectionchange: {
scope: this,
fn: function (selectionModel, selectedRecords, eventOptions) {
this.selectedIds = [];
this.selectedItems = [];
if (selectedRecords != null) {
for (var i = 0; i < selectedRecords.length; i++) {
var item = selectedRecords[i].data;
this.selectedIds.push(item[this.initParameters.storeIdProperty]);
this.selectedItems.push(item)
}
}
if (this.initParameters.selectionChangeCallback != null)
this.initParameters.selectionChangeCallback(this.selectedIds, this.selectedItems);
}
}
};
shared.MyDataGrid.superclass.initComponent.call(this);
},
getRecordCount: function () {
return this.getStore().getTotalCount();
},
getSelectedIds: function () {
return this.selectedIds;
},
getSelectedItems: function () {
return this.selectedItems;
}
});
Can anyone please explain what should I do exactly to make the grid show the updated row?
I suggest that use the following code in your 'selectionchange' event.
this.getStore().load({
params:{
'yourModelIdProperty':'selectedId'
}
});
It's call an store proxy. You should write a function for that proxy and load the updated data.

GridBooleanColumn with data first by 0 and 1 but no true and false

In my db I have a column Actif with values 0 and 1 (false and true)
I tried to use a column. Boolean with my db values 0 and 1 ... but it doesn't work.
{
xtype: 'booleancolumn',
dataIndex: 'Actif',
text: 'MyBooleanColumn',
falseText: 'Non',
trueText: 'Oui'
}
Help me please :)
My Model
Ext.define('ModuleGestion.model.UtilisateursApplicatifs', {
extend: 'Ext.data.Model',
fields: [
{
name: 'Nom'
},
{
name: 'Prenom'
},
{
name: 'Identification'
},
{
name: 'MotDePasse'
},
{
name: 'IUtilisateurApplicatif'
},
{
name: 'FonctionRepertoire'
},
{
name: 'FonctionAnimation'
},
{
name: 'FonctionFormation'
},
{
name: 'FonctionAdministration'
},
{
name: 'Actif'
}
]});
the solution is delete the double quote of the return of the values :
$resultat = json_encode($resultat );
$resultat = str_replace('"Actif":"0"', '"Actif":0', $resultat);
$resultat = str_replace('"Actif":"1"', '"Actif":1', $resultat);
I have similar situation and for work with 0 and 1 from db I use not boolean column. From db I send 0 and 1, in my column renderer I check this and make some conversions. Check my example(here's actioncolumn - it's for show icons in cells). It's one way to decision your situation.
My view:
xtype: 'actioncolumn',
width: 55,
align: 'center',
dataIndex: 'Actif',
menuDisabled: 'true'
text: '',
sortable: false,
fixed: 'true',
renderer: function (value, metadata, record) {
if (value == '0') {
//some code
}
else {
//some code
}
},
getTip: function (value, metadata, record) {
if (value == '0') {
return 'here 0';
} else {
return 'here 1';
}
}
You don't need to change model.
In your example I think you should add type of you'r field in model.
here's example
{ name: 'Actif', type: 'boolean' }

exjts hide column if all cells of the column are empty

I am trying to hide the column if all the cells in the column are empty. I am trying to do this in the column listener by iterating through the store but I guess the store isnt populated at that time. any suggestions to achieve this functionality?
Ext.define('com.abc.MyGrid' , {
extend: 'Ext.grid.Panel',
store : 'MyStore',
columns : [{
text : 'col1',
sortable : true,
dataIndex : 'col1'
}, {
text : 'col2 ',
sortable : true,
dataIndex : 'col2',
listeners:{
"beforerender": function(){
console.log(this.up('grid').store);
this.up('grid').store.each(function(record,idx){
// if all are null for record.get('col1')
// hide the column
console.log(record.get('col1'));
});
}
}
}
})
But this is isnt working. Basically the store loop in the column listener "before render" is not executing where as the above console(this.up('grid').store) prints the store with values.
Here you go, it doesn't handle everything but should be sufficient.
Ext.define('HideColumnIfEmpty', {
extend: 'Ext.AbstractPlugin',
alias: 'plugin.hideColumnIfEmpty',
mixins: {
bindable: 'Ext.util.Bindable'
},
init: function(grid) {
this.grid = grid;
this._initStates();
this.grid.on('reconfigure', this._initStates, this);
},
_initStates: function(store, columns) {
var store = this.grid.getStore(),
columns = this.grid.columns;
this.bindStore(store);
this.columns = columns;
if(store.getCount() > 0) {
this._maybeHideColumns();
}
},
/**
*#implement
*/
getStoreListeners: function() {
return {
load: this._maybeHideColumns
};
},
_maybeHideColumns: function() {
var columns = this.columns,
store = this.store,
columnKeysMc = new Ext.util.MixedCollection();
Ext.Array.forEach(columns, function(column) {
columnKeysMc.add(column.dataIndex, column);
});
Ext.Array.some(store.getRange(),function(record){
//don't saw off the branch you are sitting on
//eachKey does not clone
var keysToRemove = [];
columnKeysMc.eachKey(function(key) {
if(!Ext.isEmpty(record.get(key))) {
keysToRemove.push(key);
}
});
Ext.Array.forEach(keysToRemove, function(k) {
columnKeysMc.removeAtKey(k);
});
return columnKeysMc.getCount() === 0;
});
columnKeysMc.each(function(column) {
column.hide();
});
}
});
Here is an example:
Ext.create('Ext.data.Store', {
storeId:'simpsonsStore',
fields:['name', 'email', 'phone'],
data:{'items':[
{ 'name': 'Lisa', "email":"lisa#simpsons.com", "phone":"555-111-1224" },
{ 'name': 'Bart', "email":"bart#simpsons.com", "phone":"555-222-1234" },
{ 'name': 'Homer', "email":"home#simpsons.com", "phone":"555-222-1244" },
{ 'name': 'Marge', "email":"marge#simpsons.com", "phone":"555-222-1254" }
]},
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'items'
}
}
});
Ext.create('Ext.grid.Panel', {
title: 'Simpsons',
store: Ext.data.StoreManager.lookup('simpsonsStore'),
columns: [
{ text: 'Name', dataIndex: 'name' },
{ text: 'Email', dataIndex: 'email', flex: 1 },
{ text: 'Phone', dataIndex: 'phone' },
{ text: 'Says Doh', dataIndex: 'saysDoh'}
],
plugins: {ptype: 'hideColumnIfEmpty'},
height: 200,
width: 400,
renderTo: Ext.getBody()
});
You can see in the example that saysDoh column is hidden.
If you want to iterate over the store, you need to put a listener on the load event of your store. The beforerender doesn't mean that your store is already loaded.
I would put the creation of you store in the initComponent. Something like this:
Ext.define('com.abc.MyGrid', {
extend: 'Ext.grid.Panel',
columns: [{
text: 'col1',
sortable: true,
dataIndex: 'col1'
}, {
text: 'col2 ',
sortable: true,
dataIndex: 'col2'
},
initComponent: function () {
var me = this;
//Create store
var myStore = Ext.create('MyStore');
myStore.load(); // You can remove this if autoLoad: true on your store.
//Listen to load event (fires when loading has completed)
myStore.on({
load: function (store, records, success) {
store.each(function (record, idx) {
console.log(record.get('col1'));
});
}
});
//Apply the store to your grid
Ext.apply(me, {
store: myStore
});
me.callParent();
}
});

Categories