So i am trying to implement a pagination table with the datatables plugin, this is my first time using this plugin. I followed the documentation on the plugin and tried to get the values from the server through the use of Ajax, as per presented in the plugins documentation.
I seem to be getting the following error once i make the get request and i am unsure of why?
Error: Uncaught TypeError: Cannot read property 'length' of undefined
On client side i have the following code
viewReports = {
init: function(){
$('#paginatedData').DataTable({
"processing": true,
"serverSide": true,
"ajax": '/viewreports'
});
}
};
$(document).ready(viewReports.init);
In my server side i have the following
router.get('/viewreports', function(res, req){
async.parallel({
viewReports: function(callback){
restCall('/rest/bugbounty/latest/message/searchReport', 'POST', parameters, function(data){
callback(null, data);
});
}
}, function(err, result){
if(!err){
res.send(result.viewReports);
res.render('viewreports');
}
});
});
Returned JSON:
{ reportList: [ { reportID: 'EIBBP-448', eBayUserID: ' ', reportStatus: 'New', summary: 'BugBounty Report created by Raj', lastUpdatedDate: '2015-06-15 01:05', createdDate: '2015-06-15 01:05', paypalLoginID: 'raaj#paypal.com' } ], searchStatus: 'Success', eBayUserID: '', errorCode: '0', rowCount: '6', pageNumber: '1', paginationValue: '1', paypalLoginID: 'raaj#paypal.com' }
It would be great to know if there is anyone who has worked with node.js server side processing for datatables
You need to define dataSrc and columns.data - the following should work :
var table = $('#example').DataTable({
processing: true,
serverSide: true,
ajax: {
url: "/viewreports",
dataSrc: "reportList"
},
columns: [
{ data : "reportID" },
{ data : "eBayUserID" },
{ data : "reportStatus" },
{ data : "summary" },
{ data : "lastUpdatedDate" },
{ data : "createdDate" },
{ data : "paypalLoginID" }
]
});
on an empty table :
<table id="example"></table>
dataSrc to specify what the array holding row items is named (cause of "Cannot read property 'length' of undefined")
columns.data to map item properties to columns
You simply don't have to bother with the server side processing.
I used a simple way to trick dataTables initialization.
First, you will need to fetch the data you want to display in the table through your most preferred way, after you have confirm that data displays well, now head to where you initialize dataTables and make it so that it delays before initialization.
setTimeout(() => {
$('#yourtable').dataTable({
// datatables customization options
});
}, 100)
For example, in my case I gave it a delay of 100ms, and it works like a charm.
Related
I want to fill a jquery datatable by passing an array to it, the controller pass an array of users using ViewBag as following:
userInfo[] users = _context.userInfo.ToArray();
ViewBag.UsersArray = users;
In the view, I used ViewBag.UsersArray as a data source for the jquery datatable:
<script>
$(document).ready(function () {
$('#users').DataTable({
data: #ViewBag.UsersArray,
columns: [
{ data: 'id' },
{ data: 'username' },
{ data: 'balance' },
{ data: 'contract_id' }
]
});
});
</script>
I always got Unexpected token ']'
To use C# objects in script tags in Razor pages, you must first convert them to JSON. Razor does not do this automatically.
This way you can easily serialize your array to JSON:
<script>
$(document).ready(function () {
$('#users').DataTable({
data: #Json.Serialize(#ViewBag.UsersArray),
columns: [
{ data: 'id' },
{ data: 'username' },
{ data: 'balance' },
{ data: 'contract_id' }
]
});
});
</script>
The problem seems to just be that the array is being treated as a reference to an object rather than being enumerated. I would first try wrapping #ViewBag.UsersArray in quotes, and if that makes no difference I would "manually" enumerate through the array in your JS code and add each array element to the table's data property.
TL;DR
To make it clearer, I want to have access to ALL the data in the selected JSON object inside the onItemAdd function. Right now I only have access to _id and name via the config variables.
Ok, so I have a working Selectize.js function grabbing a JSON object from my server and creating the select options.
What I want to know is, can I get anymore data from the existing JSON object inside the "onItemSelect" callback?
The only data I can get directly is the value as specified in the config, which in this case is the "_id" and the $item which i assume is form the labelField in the config, in this case is the name form the JSON data.
How can I get more data than that for the selected item? You see in the render object I use the variable item.sku, how can I access the sku variable in the "onItemAdd" callback?
the data form the server is a json array:
[
{ _id: 'abcd1234', name: 'Sample', sku: '00123' },
{ _id: 'efgh5678', name: 'Sample2', sku: '00124' }
]
My function
// setup select box to add new products to list
$('#buyingGroupAddProducts').selectize({
valueField: '_id',
labelField: 'name',
searchField: 'name',
options: [],
create: false,
closeAfterSelect: true,
render: {
option: function(item, escape) {
return '<div>'+ escape(item.sku) + ': ' + escape(item.name) + '</div>';
}
},
load: function(query, callback) {
if (!query.length) return callback();
$.ajax({
url: '/buying/products-search',
type: 'GET',
dataType: 'json',
data: {
q: query
},
error: function() {
callback();
},
success: function(res) {
callback(res);
}
});
},
onItemAdd: function(value, $item) {
// DO the thing
console.log($item);
}
});
SelectizeJS site: http://selectize.github.io/selectize.js/
a hack to solve your problem : inside onItemAdd function you can access all your JSON : this.options gives you all the selectize options, so now you have the value and the complete JSON, you can easily find back the item in your json that corresponds to the value selected. I can complete my answer if you provide a use case in plunker.
I've searched and I can see this has been asked quite a few times, but I cant even figure out how to do a simple console.log on the data.
My store:
Ext.define('AventosPlanningTool.store.Aventos', {
extend:'Ext.data.Store',
config:
{
model:'AventosPlanningTool.model.Aventos',
proxy:
{
type:'ajax',
url:'resources/json/frames.json',
reader:
{
type:'json',
rootProperty:'options'
}
},
autoLoad: true
}
});
I can see in my network tab that the JSON file IS loading. I cannot figure out what to do with it at this point. In the data store, I've set the model to AventosPlanningTool.model.Aventos which is the file below.
Ext.define('AventosPlanningTool.model.Aventos', {
extend:'Ext.data.Model',
xtype:'AventosModel',
config:
{
fields: [
'name',
'image'
]
}
});
My JSON is pretty simple right now:
{
"name": "Cabinet Type",
"options": [
{
"name": "Face Frame",
"image": "resources/images/aventos/frames/faceframe.png"
},
{
"name": "Panel",
"image": "resources/images/aventos/frames/panel.png"
}
]
}
Even if I can do a console.log on the data that would be very helpful. I can't figure out how to use the data. I've checked both guides in the docs: http://docs-origin.sencha.com/touch/2.2.1/#!/guide/models, http://docs-origin.sencha.com/touch/2.2.1/#!/guide/stores and I just can't grasp it
Add a load listener to your store:
Ext.define('AventosPlanningTool.store.Aventos', {
extend:'Ext.data.Store',
config: {
model:'AventosPlanningTool.model.Aventos',
proxy: {
type:'ajax',
url:'resources/json/frames.json',
reader: {
type:'json',
rootProperty:'options'
}
},
autoLoad: true,
listeners: {
load: function(st, g, s, o, opts) {
st.each(function(record) {
console.log(record.get('name') + ' - ' + record.get('image'));
});
}
}
});
In sencha, data is defined in models, and actually memorized in stores. You can load your JSON through a proxy. Think of the model as the tables from sql and the store as the actual data in tables. Now, if you want to get the data from your store and perform operations on it, you have to load the store. To fetch your data into a list, you define a list with xtype:'list' specify your store store:'yourStoreName' and provide a template for showing that data. Here's a very detailed explanation on what I tried to say.
http://docs-origin.sencha.com/touch/2.2.1/#!/api/Ext.data.Store
also this:
http://miamicoder.com/2012/how-to-create-a-sencha-touch-2-app-part-2/
Look at the API docs for the data store. Note that you can only access the data once the store has been loaded. For example:
store.load();
store.getAt(0) // null, the store load hasn't completed yet.
You can loop over each record in the store using the each method. You can get a record at a particular index using getAt
store.each(function(rec) {
console.log(rec.get('name'), rec.get('image'));
});
console.log(store.getAt(0).get('name'));
Often times you will bind the store to a list, there are plenty of examples of this in the API docs.
I think what you're missing is to listen for the 'load' event on the store.
store.on('load', function(thisStore, records) {
console.log(records[0].get('name'));
})
I have a json store that returns values in json format. Now I need to get the number of rows/records in the json string but when I use store.getCount() function it returns 0, but the combobox is populated with rows, and when I use store.length I get undefined, probably because its not an array anymore, its returning from store, which is calling php script. Anyways, whats the best approach for this problem?
Try this out:
var myStore = Ext.extend(Ext.data.JsonStore, {
... config...,
count : 0,
listeners : {
load : function(){
this.count = this.getCount();
}
}
Ext.reg('myStore', myStore);
and then use inside panels:
items : [{
xtype : 'myStore',
id : 'myStoreId'
}]
Whenever you need to get the count then you can simply do this:
Ext.getCmp('myStoreId').count
Your Json response from server, can be something like this...
{
"total": 9999,
"success": true,
"users": [
{
"id": 1,
"name": "Foo",
"email": "foo#bar.com"
}
]
}
Then you can use reader: {
type : 'json',
root : 'users',
totalProperty : 'total',
successProperty: 'success'
} in your store object.
As from docs if your data source provided you can call getTotalCount to get dataset size.
If you use ajax proxy for the store, smth like
proxy : {
type : 'ajax',
url : 'YOUR URL',
reader : {
type : 'json',
root : 'NAME OF YOUR ROOT ELEMENT',
totalProperty : 'NAME OF YOUR TOTAL PROPERTY' // requiered for paging
}
}
and then load your store like
store.load();
There will be sent Ajax asynchronous request, so you should check count in callback like this
store.load({
callback : function(records, operation, success) {
console.log(this.getCount()); // count considering paging
console.log(this.getTotalCount()); // total size
// or even
console.log(records.length); // number of returned records = getCount()
}
});
I would like to save an ExtJS (3.3.1) editorgrid with a single Ajax request.
I've created an editorgrid, based on an ArrayStore.
var store = new Ext.data.ArrayStore({
data: arrayData,
fields: [ 'id', 'qty', 'idService', 'idSubscription',
'description', 'vat', 'amount' ]
});
[...]
var grid = {
xtype: 'editorgrid',
store: store,
view: gridView,
colModel: colModel,
selModel: selModel,
stripeRows: true,
tbar: tbar,
autoHeight: true,
width: 872,
clicksToEdit: 1
};
I've created a Save button with the following handler:
app.inv.saveButtonHandler = function () {
var myForm = Ext.getCmp("formHeader").getForm();
if (!myForm.isValid()) {
Ext.MessageBox.alert('Form Not Submitted',
'Please complete the form and try again.');
return;
}
myForm.el.mask('Please wait', 'x-mask-loading');
Ext.Ajax.request({
params: {
idCustomer: myForm.findField("idCustomer").getValue(),
issueDate: myForm.findField("issueDate").getValue(),
documentType: myForm.findField("documentType").getValue(),
documentNumber: myForm.findField("documentNumber").getValue()
},
url: 'save-sales-document-action',
method: 'POST',
success: function (response, request) {
myForm.el.unmask();
Ext.MessageBox.alert('Success', 'Returned: ' + response.responseText);
},
failure: function (response, request) {
myForm.el.unmask();
Ext.MessageBox.alert('Failed', 'Returned: ' + response.responseText);
}
});
};
In other words, I can send form elements with a simple value, but I don't know how to send the whole data grid. I would like to send the whole data grid with a single Ajax request.
I've already used before the cell-by-cell saving method, but in this case I would prefer to save the whole grid in one go. I don't need help for the server-side part, that I will do in Java, only for the client-side JavaScript.
Can someone help? Thanks!
After a night sleep and still no answers, I made further tries and I can answer my own question. I will leave the question open anyway, in case someone knows a better way.
To solve my problem, I added the property "storeId: 'gridStore'" to the ArrayStore, so I could locate the store later with Ext.StoreMgr.lookup(), then, at saving time, I proceed to re-build an Array record by record in the following way:
var gridData = new Array();
Ext.storeMgr.lookup('gridStore').each(function (record) {
gridData.push(record.data);
});
The essential part is that I don't get the whole Record, but only the data field of it.
After I've an array with the data, the easy part is add it to the params of Ajax.request:
params: {
...
gridData: Ext.encode(gridData)
},
This finally works. All the data is encoded in a single field. Of course on the server it will have to be decoded.