I have a problem when using a CustomField ( Name() ) within a filter that is using ds.query in order to filter, sort and reinitialize the pager for a Grid, I have created a simplified example that illustrates the problem clearly: https://jsfiddle.net/juliemontreuil/4Ls4fb19/32/
var PageSize = 5;
var data1 = [...];
var $grid = $("#BTGrid");
var sort = [{
field: "company",
dir: "asc"
}];
var dataSource = new kendo.data.DataSource({
data: data1,
schema: {
model: {
id: "Id",
fields: {
Id: {},
Firstname: {},
LastName: {},
company: {},
email: {}
},
Name: function() {
return this.get("Firstname") + " " + this.get("LastName");
}
}
},
sort: sort,
pageSize: PageSize //page size
});
$grid.kendoGrid({
dataSource: dataSource,
columns: [{
field: "Name()",
title: "Name",
}, {
field: "company",
title: "Company"
}, {
field: "email",
title: "Email"
}],
scrollable: false,
pageable: true, //enable paging
resizable: true,
sortable: {
allowUnsort: false
}
});
$('.grid-filter').off('keyup').on('keyup', function() {
var ds = $("#BTGrid").data("kendoGrid").dataSource;
// debugger;
var filterText = $(this).val();
var $filter = {
logic: "or",
filters: [{
field: "company",
operator: "contains",
value: filterText
}, {
field: "email",
operator: "contains",
value: filterText
}, {
field: "Name()",
operator: "contains",
value: filterText
}]
};
ds.query({
filter: $filter,
sort: [{
field: "company",
dir: "asc"
}],
page: 1,
pageSize: PageSize
});
});
, if you modify the var PageSize = 5; to var PageSize = 25; the filter will function correctly because the data array contains only 24 items, please advise .
I have been testing your code and I note that the Name function is the one is failing.
So I made this for you:
Solution whitout Name()
Note that now the kendogrid use a template:
$grid.kendoGrid({
dataSource: dataSource,
columns: [{
title: "Name",
template: '#= Firstname# #= LastName#',
}, {
field: "company",
title: "Company"
}, {
field: "email",
title: "Email"
}],
scrollable: false,
pageable: true, //enable paging
resizable: true,
sortable: {
allowUnsort: false
}
});
..Yes,..of course,.. now you are going to say: "How cant filter by the full name (Firstname + Lastname)?".
Well, in order to fix that situation you can declare a property (FulName) inside "data1" and then use that property in the grid and inside the filter too.
Hope this ideas works for you. :)
Here is the information about my development environment:
Microsoft Visual Studio Professional 2013
.NET Framework 4.0
jQuery-2.1.4.min.js
jQuery DataTables 1.10.7
Newtonsoft.Json.7.0.1
jQuery UI 1.11.2
var GetAUsersLogs = function (sortColumn, isDescending) {
$('#PersonalUsersLogTable').DataTable({
"aoColumns": [
{ "sTitle": "LogBsonValueId" },
{ "sTitle": "UserID" },
{ "sTitle": "Driver Name" },
{ "sTitle": "Log Date" },
{ "sTitle": "Duty Cycle" },
{
"mData": null,
"mRender": function (obj) {
return '<a href="#" id="' + obj.DT_RowId + '" onclick="ViewLogAuditHistory(this)" >Log Hist</a>';
}
},
{
"sTitle": "Details",
"mData": null,
"mRender": function (obj) {
return '<a href="#" id="' + obj.DT_RowId + '" onclick="ViewParticularLogsInfo(this)" >View</a>';
}
}
],
"aoColumnDefs": [{ "bVisible": false, "aTargets": [0, 1, 5] }],
"iDisplayLength": 5,
"sDom": '<"clear">frtip',
"bProcessing": true,
"bServerSide": true,
"bLengthChange": false,
"bPaginate": true,
"bDestroy": true,
"bSort": false,
"bInfo": true,
"bFilter": false,
"sAjaxSource": 'LogsList.aspx/BindPersonalUsersLogDataTable',
"bJQueryUI": true,
"bDeferRender": true,
"sPaginationType": "full_numbers",
"fnServerParams": function (aoData) {
aoData.push(
{ "name": "sortColumn", "value": sortColumn },
{ "name": "isDescending", "value": isDescending }
);
},
"fnServerData": function (sSource, aoData, fnCallback) {
$.ajax({
"dataType": 'json',
"contentType": "application/json; charset=utf-8",
"type": "GET",
"url": sSource,
"data": aoData,
"success":
function (msg) {
var json = jQuery.parseJSON(msg.d);
fnCallback(json);
},
beforeSend: function () {
$('.loader').show()
},
complete: function () {
$('.loader').hide()
}
});
}
}); // end of PersonalUsersLogTable DataTable method
}
// end of Code used to Bind Data to Table
The invocation to BindPersonalUsersLogDataTable method is in a C# file.
Within BindPersonalUsersLogDataTable, I will code that will determine if logged in user is an Admin or plain user.
If the logged in user is a plain user, then I want to dynamically make some of the columns in the jQuery DataTable Invisible.
Could some please tell me the changes I need to make in order to the aforementioned code to get the desired functionality?
You can use column().visible() or columns().visible() API methods to dynamically show/hide a single column or a set of columns.
"success": function (msg) {
var api = $('#PersonalUsersLogTable').DataTable();
var json = jQuery.parseJSON(msg.d);
// Enable/disable columns based on user type
if(json.isAdminUser){
api.columns([2,3]).visible(true);
} else {
api.columns([2,3]).visible(false);
}
fnCallback(json);
},
I have a dataTable in strongly typed Razor View Page.Now as per my requirement I need to populate this with my Model of the page but i am not getting how to do it.Here is my dataTable Code..
$(document).ready(function () {
var dt;
var dataSet = [];
dt = $("#Setup").dataTable({
"data": dataSet,
"paging": false,
"responsive": true,
"stateSave": true,
"columns": [
{ "title": "<input type='checkbox' id='selectAll'>", "bSortable": false, "width": "5px", },
{ "title": "", "bSortable": false, "width": "5px" },
{ "title": "Code", "width": "50px" },
{ "title": "Name" }
]
});
});
My page is Razor View Page .Please help me to get it done..Thanks..
Generally you should be able to inline your data from razor like this:
#{
StringBuilder sb = new StringBuilder();
foreach(row in model.MyTable)
{
sb.AppendFormat("['{0}', '{1}', '{2}', '{3}'],",
row.Field1, row.Field2, row.Field3, row.Field4);
}
}
$(document).ready(function () {
var dt;
var dataSet = [#Html.Raw(sb.ToString(0, sb.Length - 1))];
dt = $("#Setup").dataTable({
"data": dataSet,
"paging": false,
"responsive": true,
"stateSave": true,
"columns": [
{ "title": "<input type='checkbox' id='selectAll'>", "bSortable": false, "width": "5px", },
{ "title": "", "bSortable": false, "width": "5px" },
{ "title": "Code", "width": "50px" },
{ "title": "Name" }
]
});
});
You should use sb.Length - 1 in order to remove the last comma (,) from the output array. Using Html.Raw() prevents Razor from encoding the string which would ruin the JavaScript syntax.
It's easier: "data": #Html.Raw(Json.Encode(Model.MyList)) - For me it works.
I tried to use the dynamic attributes approach within my prototype mongoDB application.
Basically the approach just gives you something like this:
{
SKU: "Y32944EW",
type: "shoes",
attr: [
{ "k": "manufacturer",
"v": "ShoesForAll",
},
{ "k": "color",
"v": "blue",
},
{ "k": "style",
"v": "comfort",
},
{ "k": "size",
"v": "7B"
}
]
}
(Source: http://askasya.com/post/dynamicattributes).
The problem is that for example Kendo Grid does not support such nested structures in their data source.
Does anyone know if Sencha ExtJS Grid Component can do this?
Update: SKU should be a column and each v of the attr array should be a column.
Update: I am trying to setup a sencha fiddle with the help of your answer.
https://fiddle.sencha.com/#fiddle/evc
app.js (rev2)
// create the new type
Ext.data.Types.DYNAMIC = {
convert: function(value, record) {
for (var i = 0, ln = value.length; i < ln; i++) {
var item = value[i];
record.set(item.k, item.v);
}
return '';
},
type: 'dynamic',
sortType: Ext.data.SortTypes.none
};
// define a model
Ext.define('TestModel', {
extend: 'Ext.data.Model',
fields: [{name: "_id",type: "string"},
{name: "attr",type: Ext.data.Types.DYNAMIC}],
idProperty: '_id'
});
// create a store with the model assigned
Ext.create('Ext.data.Store', {
storeId: 'MyStore',
model: 'TestModel',
autoLoad: true,
proxy: {
type: 'ajax',
url: '/data.json',
reader: {
idProperty: '_id',
type: 'json',
root: 'data'
}
}
});
Ext.create('Ext.grid.Panel', {
title: 'Grid',
store: Ext.data.StoreManager.lookup('MyStore'),
columns: []
});
Ext.widget('window',{height: 200,width: 400, items: [grid ] }).show();
store.on('metachange', function(store, meta) {
grid.reconfigure(store, meta.columns);
});
data.json (rev2)
{
"metaData": {
"idProperty": "_id",
"rootProperty": "data",
"fields": [
{ "name": "_id","type": "string" },
{ "name": "de", "type":"string" },
{ "name": "en", "type":"string" },
{ "name": "fr", "type":"string" },
{ "name": "attr", "type": "dynamic"}
],
"columns": [
{
"header": "de",
"dataIndex": "de"
},
{
"header": "en",
"dataIndex": "en"
}
,
{
"header": "fr",
"dataIndex": "fr"
}
]
},
"data":
[
{"_id": "MyTextId1",
"attr":[
{
"k": "de",
"v": "GermanText Sample"
},
{
"k": "en",
"v": "English Text Sample"
},
{
"k": "fr",
"v": "French Text Sample"
},
]
},
{"_id": "MyTextId2",
"attr":[
{
"k": "de",
"v": "GermanText Sample 1"
},
{
"k": "en",
"v": "English Text Sample 1"
},
{
"k": "fr",
"v": "French Text Sample1 1"
},
]
}
]
}
Error Message:
Uncaught Error: [Ext.createByAlias] Unrecognized alias: data.field.[object Object]
Update:
Works with the snippet posted in the last edit of sra. Thank you!
Yes you can. And most of it is already Build in. Lets's start with the basics
Response MetaData
The server can return metadata in its response, in addition to the record data, that describe attributes of the data set itself or are used to reconfigure the Reader. To pass metadata in the response you simply add a metaData attribute to the root of the response data. The metaData attribute can contain anything, but supports a specific set of properties that are handled by the Reader if they are present:
root: the property name of the root response node containing the record data
totalProperty: property name for the total number of records in the data
successProperty: property name for the success status of the response
messageProperty: property name for an optional response message
fields: Config used to reconfigure the Model's fields before converting the response data into records
An initial Reader configuration containing all of these properties might look like this ("fields" would be included in the Model definition, not shown):
reader: {
type : 'json',
root : 'root',
totalProperty : 'total',
successProperty: 'success',
messageProperty: 'message'
}
If you were to pass a response object containing attributes different from those initially defined above, you could use the metaData attribute to reconifgure the Reader on the fly. For example:
{
"count": 1,
"ok": true,
"msg": "Users found",
"users": [{
"userId": 123,
"name": "Ed Spencer",
"email": "ed#sencha.com"
}],
"metaData": {
"root": "users",
"totalProperty": 'count',
"successProperty": 'ok',
"messageProperty": 'msg'
}
}
You can also place any other arbitrary data you need into the metaData attribute which will be ignored by the Reader, but will be accessible via the Reader's metaData property (which is also passed to listeners via the Proxy's metachange event (also relayed by the store). Application code can then process the passed metadata in any way it chooses.
A simple example for how this can be used would be customizing the fields for a Model that is bound to a grid. By passing the fields property the Model will be automatically updated by the Reader internally, but that change will not be reflected automatically in the grid unless you also update the column configuration. You could do this manually, or you could simply pass a standard grid column config object as part of the metaData attribute and then pass that along to the grid. Here's a very simple example for how that could be accomplished:
// response format:
{
...
"metaData": {
"fields": [
{ "name": "userId", "type": "int" },
{ "name": "name", "type": "string" },
{ "name": "birthday", "type": "date", "dateFormat": "Y-j-m" }
],
"columns": [
{ "text": "User ID", "dataIndex": "userId", "width": 40 },
{ "text": "User Name", "dataIndex": "name", "flex": 1 },
{ "text": "Birthday", "dataIndex": "birthday", "flex": 1, "format": 'Y-j-m', "xtype": "datecolumn" }
]
}
}
The Reader will automatically read the meta fields config and rebuild the Model based on the new fields, but to handle the new column configuration you would need to handle the metadata within the application code. This is done simply enough by handling the metachange event on either the store or the proxy, e.g.:
var store = Ext.create('Ext.data.Store', {
...
listeners: {
'metachange': function(store, meta) {
myGrid.reconfigure(store, meta.columns);
}
}
});
That for the basics. Now the details for your data-structure:
first we need a converter function to read the custom data
convert: function(value,record) {
for(var i=0,ln=value.length;i<ln;i++) {
var item = value[i];
record.set(item.k,item.v);
}
return ''; let's save memory an drop it
}
and we can publish the basic fields (and columns (not displayed)) - but we don't need becaouse the metachange can handle it all
{ name: "SKU", type:"string") }, // don't forget to mark this as the idProperty in the reader and in the model
{ name: "type", type:"string") },
{ name: "attr", type:"auto", convert: convert() }
all fields & columns below are published by the server with metachange
"metaData": {
"fields": [
{ name: "SKU", type:"string") },
{ name: "type", type:"string") },
{ name: "attr", type:"auto", convert: convert() },
// and the dynamic datafields
{ name: "manufacturer", type:"string" },
{ name: "style", type:"string" },
// ... and so on
],
"columns": [
{ "text": "ID", "dataIndex": "SKU", "width": 40 },
{ "text": "ID", "dataIndex": "SKU", "width": 40 },
// and the dynamic datacolumns
{ "text": "Manufacturer", "dataIndex": "manufacturer" },
{ "text": "Style", "dataIndex": "stlye" },
// ... and so on
]
}
Edit:
I recommend to either create your own reader which transform the data to a normalized JSON before processing it further or your own Ext.data.Types type. Because I think it is a bit faster I recommend to create your own data-type. The downside in your case is, that the field with this property need to be always AFTER the dynamic field, otherwise the reader will override the dynamic fields.
Here is a snipped that I tested with 4.2.3
// create the new type
Ext.data.Types.DYNAMIC = {
convert: function(value, record) {
for (var i = 0, ln = value.length; i < ln; i++) {
var item = value[i];
record.data[item.k] = item.v;
}
return '';
},
type: 'dynamic',
sortType: Ext.data.SortTypes.none
};
// define a model
Ext.define('TestModel', {
extend: 'Ext.data.Model',
fields: [{name: "_id",type: "string"},
{name: "attr",type: "dynamic"}],
idProperty: '_id'
});
// create a store with the model assigned
Ext.create('Ext.data.Store', {
storeId: 'MyStore',
model: 'TestModel',
autoLoad: true,
proxy: {
type: 'ajax',
url: '/data.json',
reader: {
idProperty: '_id',
type: 'json',
root: 'data'
}
}
});
Ext.create('Ext.grid.Panel', {
title: 'Grid',
store: Ext.data.StoreManager.lookup('MyStore'),
columns: []
});
Ext.widget('window',{height: 200,width: 400, items: [grid ] }).show();
store.on('metachange', function(store, meta) {
grid.reconfigure(store, meta.columns);
});
And the data
{
"metaData": {
"idProperty": "_id",
"rootProperty": "data",
"fields": [
{ "name": "_id","type": "string" },
{ "name": "de", "type":"string" },
{ "name": "en", "type":"string" },
{ "name": "fr", "type":"string" },
{ "name": "attr", "type": "dynamic" }
],
"columns": [
{
"header": "de",
"dataIndex": "de"
},
{
"header": "en",
"dataIndex": "en"
}
,
{
"header": "fr",
"dataIndex": "fr"
}
]
},
"data":
[
{"_id": "MyTextId1",
"attr":[
{
"k": "de",
"v": "GermanText Sample"
},
{
"k": "en",
"v": "English Text Sample"
},
{
"k": "fr",
"v": "French Text Sample"
},
]
},
{"_id": "MyTextId2",
"attr":[
{
"k": "de",
"v": "GermanText Sample 1"
},
{
"k": "en",
"v": "English Text Sample 1"
},
{
"k": "fr",
"v": "French Text Sample1 1"
},
]
}
]
}
Edit:
This snipped is tested in 5.1 and it worked
Ext.data.Types.DYNAMIC = {
convert: function(value, record) {
for (var i = 0, ln = value.length; i < ln; i++) {
var item = value[i];
record.data[item.k] = item.v;
}
return '';
},
type: 'dynamic',
sortType: Ext.data.SortTypes.none
};
Ext.define('Ext.data.field.Dynamic', {
extend: 'Ext.data.field.Field',
alias: 'data.field.dynamic',
sortType: 'none',
isDynamicField: true,
convert: function(value, record) {
for (var i = 0, ln = value.length; i < ln; i++) {
var item = value[i];
record.data[item.k] = item.v;
}
return '';
},
getType: function() {
return 'dynamic';
}
});
Ext.define('TestModel', {
extend: 'Ext.data.Model',
fields: [{name: "_id",type: "string"},{name: "attr",type: "dynamic"}],
idProperty: '_id'
});
var store = Ext.create('Ext.data.Store', {
storeId: 'MyStore',
model: 'TestModel',
autoLoad: true,
proxy: {
type: 'ajax',
url: '/qat/Content/TST/data.js',
reader: {
idProperty: '_id',
type: 'json',
rootProperty: 'data'
}
}
});
var grid = Ext.create('Ext.grid.Panel', {
title: 'Grid',
store: Ext.data.StoreManager.lookup('MyStore'),
dockedItems: [{xtype: 'pagingtoolbar',store: Ext.data.StoreManager.lookup('MyStore'), dock: 'bottom',displayInfo: false}],
columns: []
});
Ext.widget('window',{height: 200,width: 400, items: [grid ] }).show();
store.on('metachange', function(store, meta) {
// Apply the column definitions to the Grid
grid.reconfigure(store, meta.columns);
});
I am using Jquery DataTable TableTool in my MVC4 ASP.NET web application. Export to Excel and PDF working well with Chrome. But not working in IE and FireFox.
My code is given below
dom: 'T<"clear">lfrtip',
tableTools: {
"sSwfPath": "../media/swf/copy_csv_xls_pdf.swf",
"aButtons": [
{
"sExtends": "xls",
"sFileName": "Orders.csv",
"bFooter": false,
"mColumns": "visible",
"bHeader":false
}
]
},
Any one please help me
var oTable1 = $('#Ccctbl').dataTable({
"bPaginate": true,
"bDeferRender": true,
"bProcessing": true,
"bJQueryUI": true,
"sDom": '<"toolbar">frtip',
"sAjaxSource": "/Setup/LoadCostCenterCategory/",
"iDisplayLength": 15,
"bDestroy": true,
"fnPreDrawCallback": function (oSettings, json) {
var id = $(this).attr('id');
$("#ToolTables_" + id + "_0").html("<i class='icon-copy bigger-120 blue'></i>")
$("#ToolTables_" + id + "_1").html("<i class='icon-file-text green bigger-120'></i>")
$("#ToolTables_" + id + "_0").attr("title", "Copy");
$("#ToolTables_" + id + "_1").attr("title", "Export To Excel");
},
"sDom": "<'row-fluid'<'span6'T><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>",
"oTableTools": {
"sSwfPath": "//cdn.datatables.net/tabletools/2.2.2/swf/copy_csv_xls.swf",
"aButtons": [
{
'sExtends': 'copy',
"oSelectorOpts": { filter: 'applied', order: 'current' },
},
{
'sExtends': 'xls',
"oSelectorOpts": { filter: 'applied', order: 'current' },
}
]
},
"aoColumns": [
{ "mData": "CODE", "sTitle": "Cost Center Category Code", "sWidth": "25%", "bSortable": false },
{ "mData": "DESCRIPTION", "sTitle": "Description", "sWidth": "25%", "bSortable": false },
{ "mData": "strsegcattype", "sTitle": "Segment", "sWidth": "25%", "bSortable": false },
{ "mData": "strIsActive", "sTitle": "Active", "sWidth": "25%", "bSortable": false },
]
});