I am loading an observable array via ajax, hooking up to a table and then adding sorting to the column headers. It works but only sorts random rows. If I bypass the ajax feed and manually declare the observable array, all works well. Am I missing something obvious here?
//The Page
$(document).ready(function () {
var pageModel = function () {
var self = this;
//Variables and observables
self.loading = ko.observable(false);
self.searchQuery = ko.observable("");
self.searchCelebrantId = ko.observable(-1);
//Models used in page
self.celebrantsInstance = ko.observable(new celebrantsModel());
self.marriagesInstance = ko.observable(new marriagesModel());
//var celebrantsInstance = new celebrantsModel();
//var marriageInstance = new singleMarriageModel(1);
//Get data
self.loadData = function () {
return $.when(
self.celebrantsInstance().loadData()
//, self.marriagesInstance().loadData()
);
}
}
var pageInstance = new pageModel({});
pageInstance.loadData()
.done(function () {
setTimeout(function () {
ko.applyBindings(pageInstance);
/* Bootstrap select */
$("select").selectpicker();
$("select").addClass('show-menu-arrow').selectpicker('setStyle');
}, 500);
});
});
//The knockout .js model file
function marriage(data) {
var self = this;
self.id = ko.observable(data.Id);
self.CelebrantId = ko.observable(data.CelebrantId);
self.MarriageDate = ko.observable(data.MarriageDate);
self.MarriagePlace = ko.observable(data.MarriagePlace);
self.WifeFirstName = ko.observable(data.WifeFirstName);
self.WifeMaidenName = ko.observable(data.WifeMaidenName);
self.HusbandFirstName = ko.observable(data.HusbandFirstName);
self.HusbandSurname = ko.observable(data.HusbandSurname);
self.MarriageCertificateNumberToRegistrar = ko.observable(data.MarriageCertificateNumberToRegistrar);
self.MarriageCertificateNumberToCouple = ko.observable(data.MarriageCertificateNumberToCouple);
}
function GetMarriageList(searchQuery) {
return $.ajax("/Marriage/GetMarriageList?searchQuery=" + searchQuery, {
type: "get"
});
};
function GetMarriage(id) {
return $.ajax("/Marriage/GetMarriage?id=" + id, {
type: "get"
});
};
var marriagesModel = function () {
var self = this;
self.loading = ko.observable(false);
self.searchQuery = ko.observable("a");
self.searchCelebrantId = ko.observable(-1);
self.marriages = ko.observableArray([]);
self.sortCommand = ko.observable("MarriagePlace asc");
self.headers = [
// { title: 'Marriage Date', sortPropertyName: 'MarriageDate', asc: true },
{ title: 'Marriage Place', sortPropertyName: 'MarriagePlace', asc: true },
{ title: 'Wife First Name', sortPropertyName: 'WifeFirstName', asc: true },
{ title: 'Wife Maiden Name', sortPropertyName: 'WifeMaidenName', asc: true },
{ title: 'Husband First Name', sortPropertyName: 'HusbandFirstName', asc: true },
{ title: 'Husband Surname', sortPropertyName: 'HusbandSurname', asc: true },
{ title: ' Marriage Certificate\nTo Registrar', sortPropertyName: 'MarriageCertificateNumberToRegistrar', asc: true },
{ title: 'Marriage Certificate \nTo Couple', sortPropertyName: 'MarriageCertificateNumberToCouple', asc: true },
{ title: '' },
];
self.activeSort = self.headers[0]; //set the default sort
self.sort = function (header, event) {
//if this header was just clicked a second time
if (self.activeSort === header) {
header.asc = !header.asc; //toggle the direction of the sort
} else {
self.activeSort = header; //first click, remember it
}
var prop = self.activeSort.sortPropertyName;
var ascSort = function (a, b) { return a[prop] < b[prop] ? -1 : a[prop] > b[prop] ? 1 : a[prop] == b[prop] ? 0 : 0; };
var descSort = function (a, b) { return a[prop] > b[prop] ? -1 : a[prop] < b[prop] ? 1 : a[prop] == b[prop] ? 0 : 0; };
var sortFunc = self.activeSort.asc ? ascSort : descSort;
self.marriages.sort(sortFunc);
};
self.loadData = function () {
self.loading(true);
return GetMarriageList(self.searchQuery())
.done(function (data) {
var mappedMarriages = $.map(data, function (item) {
return new marriage(item);
});
self.marriages(mappedMarriages);
self.loading(false);
});
}
return GetMarriageList(self.searchQuery())
.done(function (data) {
var mappedMarriages = $.map(data, function (item) {
return new marriage(item);
});
self.marriages(mappedMarriages);
self.loading(false);
});
}
//HTML Table
<table id="event-table" class="table table-striped" style="width: 100%; display: none" data-bind="visible: (!loading() && marriages().length > 0)">
<tr data-bind="foreach: headers">
<th data-bind="click: sort, text: title"></th>
</tr>
<!-- ko foreach: marriages -->
<tr>
<!--<td style="width: 120px"><span data-bind='html: moment(MarriageDate()).format("DD/MM/YYYY")'></span></td>-->
<td><span data-bind='html: MarriagePlace'></span></td>
<td><span data-bind='html: WifeFirstName'></span></td>
<td><span data-bind='html: WifeMaidenName'></span></td>
<td><span data-bind='html: HusbandFirstName'></span></td>
<td><span data-bind='html: HusbandSurname'></span></td>
<td><span data-bind='html: MarriageCertificateNumberToRegistrar'></span></td>
<td><span data-bind='html: MarriageCertificateNumberToCouple'></span></td>
<td><a data-bind='attr: { "href": "/Marriage/Edit/" + id }'>Edit</a></td>
</tr>
<!-- /ko -->
</table>
You might want to have a look at knockout-transformations.
Cheers
Related
I have a lot of problem to upload multiple images using AJAX. I write this code:
HTML
<form id="upload" method="post" enctype="multipart/form-data">
<div id="drop" class="drop-area">
<div class="drop-area-label">
Drop image here
</div>
<input type="file" name="file" id="file" multiple/>
</div>
<ul class="gallery-image-list" id="uploads">
<!-- The file uploads will be shown here -->
</ul>
</form>
<div id="listTable"></div>
jQuery/AJAX
$(document).on("change", "input[name^='file']", function(e){
e.preventDefault();
var This = this,
display = $("#uploads");
// list all file data
$.each(This.files, function(i, obj){
// for each image run script asynchronous
(function(i) {
// get data from input file
var file = This.files[i],
name = file.name,
size = file.size,
type = file.type,
lastModified = file.lastModified,
lastModifiedDate = file.lastModifiedDate,
webkitRelativePath = file.webkitRelativePath,
slice = file.slice,
i = i;
// DEBUG
/*
var acc = []
$.each(file, function(index, value) {
acc.push(index + ": " + value);
});
alert(JSON.stringify(acc));
*/
$.ajax({
url:'/ajax/upload.php',
contentType: "multipart/form-data",
data:{
"image":
{
"name":name,
"size":size,
"type":type,
"lastModified":lastModified,
"lastModifiedDate":lastModifiedDate,
"webkitRelativePath":webkitRelativePath,
//"slice":slice,
}
},
type: "POST",
// Custom XMLHttpRequest
xhr: function() {
var myXhr = $.ajaxSettings.xhr();
// Check if upload property exists
if(myXhr.upload)
{
// For handling the progress of the upload
myXhr.upload.addEventListener("progress",progressHandlingFunction, false);
}
return myXhr;
},
cache: false,
success : function(data){
// load ajax data
$("#listTable").append(data);
}
});
// display progress
function progressHandlingFunction(e){
if(e.lengthComputable){
var perc = Math.round((e.loaded / e.total)*100);
perc = ( (perc >= 100) ? 100 : ( (perc <= 0) ? 0 : 0 ) );
$("#progress"+i+" > div")
.attr({"aria-valuenow":perc})
.css("width", perc+"%");
}
}
// display list of files
display.append('<li>'+name+'</li><div class="progress" id="progress'+i+'">'
+'<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">'
+'</div></div>');
})(i);
});
});
I've tried a various versions and I never succeed to send multiple data through ajax. I have tried in this way what you see above, and now I get only POST informations. I understand why i get POST but I need to send FILES information and I do not know where I'm wrong.
I not work the first time with ajax and often use it for most projects but I have never used to send multiple files and that bothering me now.
Thanks!
Try utilizing json to upload , process file object
html
<div id="drop" class="drop-area ui-widget-header">
<div class="drop-area-label">Drop image here</div>
</div>
<br />
<form id="upload">
<input type="file" name="file" id="file" multiple="true" accepts="image/*" />
<ul class="gallery-image-list" id="uploads">
<!-- The file uploads will be shown here -->
</ul>
</form>
<div id="listTable"></div>
css
#uploads {
display:block;
position:relative;
}
#uploads li {
list-style:none;
}
#drop {
width: 90%;
height: 100px;
padding: 0.5em;
float: left;
margin: 10px;
border: 8px dotted grey;
}
#drop.hover {
border: 8px dotted green;
}
#drop.err {
border: 8px dotted orangered;
}
js
var display = $("#uploads"); // cache `#uploads`, `this` at `$.ajax()`
var droppable = $("#drop")[0]; // cache `#drop` selector
$.ajaxSetup({
context: display,
contentType: "application/json",
dataType: "json",
beforeSend: function (jqxhr, settings) {
// pre-process `file`
var file = JSON.parse(
decodeURIComponent(settings.data.split(/=/)[1])
);
// add `progress` element for each `file`
var progress = $("<progress />", {
"class": "file-" + (!!$("progress").length
? $("progress").length
: "0"),
"min": 0,
"max": 0,
"value": 0,
"data-name": file.name
});
this.append(progress, file.name + "<br />");
jqxhr.name = progress.attr("class");
}
});
var processFiles = function processFiles(event) {
event.preventDefault();
// process `input[type=file]`, `droppable` `file`
var files = event.target.files || event.dataTransfer.files;
var images = $.map(files, function (file, i) {
var reader = new FileReader();
var dfd = new $.Deferred();
reader.onload = function (e) {
dfd.resolveWith(file, [e.target.result])
};
reader.readAsDataURL(new Blob([file], {
"type": file.type
}));
return dfd.then(function (data) {
return $.ajax({
type: "POST",
url: "/echo/json/",
data: {
"file": JSON.stringify({
"file": data,
"name": this.name,
"size": this.size,
"type": this.type
})
},
xhr: function () {
// do `progress` event stuff
var uploads = this.context;
var progress = this.context.find("progress:last");
var xhrUpload = $.ajaxSettings.xhr();
if (xhrUpload.upload) {
xhrUpload.upload.onprogress = function (evt) {
progress.attr({
"max": evt.total,
"value": evt.loaded
})
};
xhrUpload.upload.onloadend = function (evt) {
var progressData = progress.eq(-1);
console.log(progressData.data("name")
+ " upload complete...");
var img = new Image;
$(img).addClass(progressData.eq(-1)
.attr("class"));
img.onload = function () {
if (this.complete) {
console.log(
progressData.data("name")
+ " preview loading..."
);
};
};
uploads.append("<br /><li>", img, "</li><br />");
};
}
return xhrUpload;
}
})
.then(function (data, textStatus, jqxhr) {
console.log(data)
this.find("img[class=" + jqxhr.name + "]")
.attr("src", data.file)
.before("<span>" + data.name + "</span><br />");
return data
}, function (jqxhr, textStatus, errorThrown) {
console.log(errorThrown);
return errorThrown
});
})
});
$.when.apply(display, images).then(function () {
var result = $.makeArray(arguments);
console.log(result.length, "uploads complete");
}, function err(jqxhr, textStatus, errorThrown) {
console.log(jqxhr, textStatus, errorThrown)
})
};
$(document)
.on("change", "input[name^=file]", processFiles);
// process `droppable` events
droppable.ondragover = function () {
$(this).addClass("hover");
return false;
};
droppable.ondragend = function () {
$(this).removeClass("hover")
return false;
};
droppable.ondrop = function (e) {
$(this).removeClass("hover");
var image = Array.prototype.slice.call(e.dataTransfer.files)
.every(function (img, i) {
return /^image/.test(img.type)
});
e.preventDefault();
// if `file`, file type `image` , process `file`
if (!!e.dataTransfer.files.length && image) {
$(this).find(".drop-area-label")
.css("color", "blue")
.html(function (i, html) {
$(this).delay(3000, "msg").queue("msg", function () {
$(this).css("color", "initial").html(html)
}).dequeue("msg");
return "File dropped, processing file upload...";
});
processFiles(e);
} else {
// if dropped `file` _not_ `image`
$(this)
.removeClass("hover")
.addClass("err")
.find(".drop-area-label")
.css("color", "darkred")
.html(function (i, html) {
$(this).delay(3000, "msg").queue("msg", function () {
$(this).css("color", "initial").html(html)
.parent("#drop").removeClass("err")
}).dequeue("msg");
return "Please drop image file...";
});
};
};
php
<?php
if (isset($_POST["file"])) {
// do php stuff
// call `json_encode` on `file` object
$file = json_encode($_POST["file"]);
// return `file` as `json` string
echo $file;
};
jsfiddle http://jsfiddle.net/guest271314/0hm09yqo/
I have a little problem.
When adding my table the element "scrollX": true, the search entries disappear.
CODE:
JAVASCRIPT
function parametrosTabla6(tabla) {
var tabla2 = $(tabla).DataTable({
'paging': true,
'searching': true,
'ordering': true,
'orderCellsTop': true,
'order': [
[0, 'desc']
],
"scrollX": true,
'columnDefs': [
{
'responsivePriority': 1,
'targets': 0
},
{
'responsivePriority': 2,
'targets': -1
},
{ "className": "dt-center", "targets": "_all" }
],
'responsive': true,
});
var len = $('#datos thead tr:eq(1) th').length;
$('#datos tfoot:eq(0) th').each(function (i, e) {
var title = $(this).text();
if (i == len - 1) { } else {
$(this).html('<input style="width:100%" class="form-control" data-column="' + (i + 1) + '" type="text" placeholder="' + title + '" />');
}
$('input', this).on('keyup change', function () {
if (tabla2.column(i).search() !== this.value) {
tabla2.column(i).search(this.value).draw();
}
});
});
}
HTML/CSS/PHP
<table id="datos" class="table table-hover display drtresponsive nowrap" width="100%">
<thead>
<th>Nº Pedido</th>
<th>Cliente</th>
<th>Nº Telefono (fijo-movil)</th>
<th>Fecha Venta</th>
<th>Correo Enviado</th>
<th>Estado Pago</th>
<th>Expedicion</th>
<th>Fecha Envio</th>
<th>Fecha Entrega</th>
<th>Recibido</th>
<th>Anulado</th>
<th>Usuario Venta</th>
<th>Ultimo usuario editado</th>
<th>Acciones Disponibles</th>
</thead>
<tfoot style="display: table-header-group">
<tr>
<th>Nº Pedido</th>
<th>Cliente</th>
<th>Nº Telefono (fijo-movil)</th>
<th>Fecha Venta</th>
<th>Correo Enviado</th>
<th>Estado Pago</th>
<th>Expedicion</th>
<th>Fecha Envio</th>
<th>Fecha Entrega</th>
<th>Recibido</th>
<th>Anulado</th>
<th>Usuario Venta</th>
<th>Ultimo usuario editado</th>
<th>Acciones Disponibles</th>
</tr>
</tfoot>
<tbody>
<?php
if (isset($result)) {
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
switch ($row['recibido']) {
case 0:
$row['recibido'] = "NO";
break;
case 1:
$row['recibido'] = "SI";
break;
}
switch ($row['correo_confirmacion']) {
case 0:
$row['correo_confirmacion'] = "NO";
break;
case 1:
$row['correo_confirmacion'] = "SI";
break;
}
switch ($row['factura']) {
case 0:
$row['factura'] = "NO";
break;
case 1:
$row['factura'] = "SI";
break;
}
switch ($row['anulado']) {
case 0:
$row['anulado'] = "NO";
break;
case 1:
$row['anulado'] = "SI";
break;
}
require 'mod/tabla_facturas.php';
}
} else {
echo "<tr>0 results</td>";
}
} else {
echo "<td colspan='100%'>0 results</td>";
}
?>
</tbody>
</table>
Here is the answer.
You have two options:
(The one I have chosen) Put the overflow-x:auto in parent div.
Clone the thead and add the inputs.
var len = $('#datos thead tr:eq(1) th').length;
$('#datos thead tr').clone(true).appendTo('#datos thead');
$('#datos thead tr:eq(1) th').each(function (i, e) {
var title = $(this).text();
if (i == len - 1) {
} else {
$(this).html('<input style="width:100%" type="text" placeholder="' + title + '" />');
}
$('input', this).on('keyup change', function () {
if (table.column(i).search() !== this.value) {
table
.column(i)
.search(this.value)
.draw();
}
});
});
Add the orderCellsTop option to the datatable.
I want to display remove and Edit Icon in order summary section in checkout page, I have tried below changes:
/magento_demo/vendor/magento/module-checkout/view/frontend/web/template/summary/item/details.html
I have added Edit / Delete links like this:
<div class="primary">
<a data-bind="attr: {href: getConfigUrl($parent.item_id),title: $t('Edit item')}" class="action edit">
<span data-bind="i18n: 'Edit'"></span>
</a>
</div>
<div class="secondary">
<a href="#" data-bind="attr: {'data-post': getDataPost($parent.item_id),title: $t('Delete item')}" class="action delete">
<span data-bind="i18n: 'Remove'"></span>
</a>
</div>
In
/magento_demo/vendor/magento/module-checkout/view/frontend/web/js/view/summary/item/details.js
I have done below changes:
define(
[
'uiComponent',
'mage/url',
'Magento_Customer/js/customer-data',
'jquery',
'ko',
'underscore',
'sidebar',
'mage/translate'
],
function (Component,url,customerData,$,ko, _) {
"use strict";
return Component.extend({
defaults: {
template: 'Magento_Checkout/summary/item/details'
},
getValue: function(quoteItem) {
var itemId = elem.data('cart-item'),
itemQty = elem.data('item-qty');
return quoteItem.name;
},
getDataPost: function(itemId) {
console.log(itemId);
var itemsData = window.checkoutConfig.quoteItemData;
var obj = {};
var obj = {
data: {}
};
itemsData.forEach(function (item) {
if(item.item_id == itemId) {
var mainlinkUrl = url.build('checkout/cart/delete/');
var baseUrl = url.build('checkout/cart/');
console.log(mainlinkUrl);
obj.action = mainlinkUrl;
obj.data.id= item.item_id;
obj.data.uenc = btoa(baseUrl);
}
});
return JSON.stringify(obj);
},
getConfigUrl: function(itemId) {
var itemsData = window.checkoutConfig.quoteItemData;
var configUrl = null;
var mainlinkUrl = url.build('checkout/cart/configure');
var linkUrl;
itemsData.forEach(function (item) {
var itm_id = item.item_id;
var product_id = item.product.entity_id;
if(item.item_id == itemId) {
linkUrl = mainlinkUrl+"/id/"+itm_id+"/product_id/"+product_id;
}
});
if(linkUrl != null) {
return linkUrl;
}
else {
return '';
}
}
});
}
);
But when I click on delete button, it just redirecting to cart page but not deleting product, what can be the issue here.
Have component that works with React, Redux and AJAX:
class IncomeProfile extends Component {
constructor(props) {
super(props)
this.state = {
items: this.props.items || []
}
}
componentDidMount() {
this.props.IncomeListProfile();
}
componentWillReceiveProps(nextProps) {
this.setState({ items: nextProps.items });
}
filterList(event) {
var updatedList = this.state.items;
updatedList = updatedList.filter(function(item) {
return item.toLowerCase().search(event.target.value.toLowerCase()) !== -1;
});
this.setState({items: updatedList}); // now this.state.items has a value
}
render() {
var elems = this.props.items;
if (typeof elems == 'undefined') {
elems = [];
}
//console.log(elems);
return (
<div>
<table className='table'>
<thead className='theadstyle'>
<th>date
<input></input>
</th>
<th>
<input onChange={this.filterList} type='text' placeholder='keyword search'></input>
</th>
<th>
<input type='text' placeholder='amount search'></input>
</th>
<th>amount</th>
<th>Show archived</th>
</thead>
<div className='tbodymar'></div>
<tbody >
{elems.map((item) => (
<tr key={item.course_id}>
<td>{item.created_at}</td>
<td>{item.name}</td>
<td>{item.remark}</td>
<td>{item.income_amount}</td>
<td>more options</td>
</tr>
))}
</tbody>
</table>
</div>
)
}
}
const mapDispatchToProps = function(dispatch) {
return {
IncomeListProfile: () => dispatch(IncomeProfileList())
}
}
const mapStateToProps = function(state) {
//var mystore = state.toJS()
var mystore = state.getIn(['incomeProfileList'])['course_list'];
//console.log(mystored.hh);
var copy = Object.assign({}, mystore);
return {items: copy.course_list};
}
export default connect(mapStateToProps, mapDispatchToProps)(IncomeProfile);
When I enter something in input, I get error Cannot read property 'state' of undefined, but console.log show's my state. What wrong with filter ? Where mistake? if I had right state?
this.props.items only get populate after componentDidMount?
If so, and you want to set the items in the state too. You can use componentWillReceiveProps method to set the new props to you state.
componentWillReceiveProps(nextProps) {
this.setState({ items: nextProps.items });
}
I am looking for code to have below features with HTML table.
Design a reusable grid which has the below default features:
Ajax enabled Table ( No Post backs)
Paging through Ajax Calls
Sorting through Ajax calls
Filtering through Ajax calls
You can use jQuery datatables.net for this task.You can download js file from here
download JS file
here i am going to explain a sample for the same.i have used entity framework to fetch the data from back-end.if you are not using entity framework then get the concept from this sample and implement it on your way.
HTML:
<table id="tblList" cellpadding="0" cellspacing="0" border="0" class="grid" >
<thead>
<tr>
<th class="headingtextcenter">#</th><th class="headingtextcenter">Name</th><th class="headingtextcenter">Description</th>
<th class="headingtextcenter">Form Publish Date</th><th class="headingtextcenter">Last Data Entery Date</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script src="Scripts/jquery-1.7.2.js" type="text/javascript"></script>
<script src="Scripts/jquery.dataTables.js" type="text/javascript"></script>
<script type="text/javascript" language="javascript">
$(window).load(function () {
var oTable = $('#tblList').dataTable({
"bServerSide": true,
"sAjaxSource": "List.aspx?load=1",
"bProcessing": true,
"sPaginationType": "full_numbers",
"oLanguage": { "sZeroRecords": "<div style='width:99%;text-align:center;padding:4px;'>No record found.</div>" },
"aoColumns": [
{ "sName": "ID","bSortable": false },
{ "fnRender": function (oObj) {
return '<a href=\"Whitepaper/' +
oObj.aData[3] + '\" >' + oObj.aData[0] + '</a>';
},"bSortable": false },
{ "sName": "Description", "bSortable": false},
{ "sName": "FormPublishDate", "bSortable": false},
{ "sName": "LastDataEnteryDate"}
],
"fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
$('td', nRow).addClass("cells");
}
});
});
</script>
//User fnRowCallback function if you want to add css to all td
Code Behind(List.aspx.cs):
private FormEntities objEntities;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (Request.QueryString["load"] != null && Request.QueryString["load"].ToString() == "1")
BindData();
}
}
private void BindData()
{
using (objEntities = new FormEntities())
{
//For sorting
Func<Forms, string> orderingFunction = (c => c.LastDataEnteryDate);
var sortDirection = Request["sSortDir_0"];
IEnumerable<Forms> allForms = objEntities.Forms;
var sSearch = Convert.ToString(Request["sSearch"]);
if (!string.IsNullOrEmpty(sSearch))
{
allVideoLibraries = allForms.Where(c => c.LastDataEnteryDate.ToLower().Contains(sSearch.ToLower()));
}
if (sortDirection == "asc")
allForms = allForms.OrderBy(orderingFunction);
else if (sortDirection == "desc")
allForms = allForms.OrderByDescending(orderingFunction);
var displayForms = allForms.Skip(int.Parse(Request.QueryString["iDisplayStart"])).Take(int.Parse(Request.QueryString["iDisplayLength"]));
var result = from v in displayForms
select new[] { v.ID,v.Name, v.Description, v.FormPublishDate ,v.LastDataEnteryDate };
JavaScriptSerializer toJSON = new JavaScriptSerializer(); //need to add reference using System.Web.Script.Serialization;
Response.Clear();
string datastring = toJSON.Serialize(new
{
sEcho = Request.QueryString["sEcho"],
iTotalRecords = result.Count(),
iTotalDisplayRecords = result.Count(),
aaData = result
});
Response.Write(datastring);
Response.End();
}
}