I'm using EF6 + MVC for a site. The dataTables editor is used for an UI. One table has a field 'StartDate'. It is a datetime type in the SQL Server.
It works fine until when I try to edit the 'StartDate' value. From the browser debug, I can see that the JSON send from backend to UI is in the timestamp format, i.e. /Date(1541923200000)/ .
In the dataTables, I convert this to the correct local datetime format, so it shows correctly.
However, I could not figure out how to do this in Editor plugin. It always shows the /Date(1541923200000)/ .
The code I use is:
editorAdvertisement = new $.fn.dataTable.Editor({
ajax: '/APN/GetAdvertisementData',
table: "#tblAdvertisements",
fields: [{
label: "StartDate",
name: "AdvStartDate"
, type: "datetime"
, format: 'MM\/DD\/YYYY h:mm a'
}, {
label: "Deadline",
name: "AdvDeadline"
, type: "datetime"
}, {
label: "TitleOfAdv",
name: "TitleOfAdv"
}, {
label: "ListPrice",
name: "ListPrice"
}
]
});
var tbl = $('#tblAdvertisements').DataTable({
pageLength: 10,
dom: '<"html5buttons"B>lTfgitp',
ajax: '/APN/GetAdvertisementData'
,
columns: [
{
data: "AdvStartDate", name: "AdvStartDate"
, type: "datetime"
, render: function (value) {
var r = convertDate(value);
return r;
}
, "autoWidth": true
},
{
data: "AdvDeadline", name: "AdvDeadline"
, type: "datetime"
, render: function (value) {
var r = convertDate(value);
return r;
}
, "autoWidth": true
},
{ data: "TitleOfAdv", name: "TitleOfAdv", "autoWidth": true },
{
data: "ListPrice", name: "ListPrice", "autoWidth": true
, render: $.fn.dataTable.render.number(',', '.', 0, '$')
}
],
order: [1, 'asc'],
select: {
style: 'os',
selector: 'td:first-child'
},
buttons: [
{ extend: "create", editor: editorAdvertisement }
, { extend: "edit", editor: editorAdvertisement }
, { extend: "remove", editor: editorAdvertisement }
]
, select: true
, searching: false
, paging: false
});
In the controller
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult GetAdvertisementData()
{
var request = HttpContext.Request.Form;
var settings = Properties.Settings.Default;
using (var db = new Database(settings.DbType, settings.DbConnection))
{
var response = new Editor(db, "Advertising", new[] { "AdvertisingID" })
.TryCatch(false)
.Model<Advertising2>()
.Field(new Field("AdvStartDate")
.Validator(Validation.DateFormat(
"MM/dd/yyyy",
new ValidationOpts { Message = "Please enter a date in the format MM/dd/yyyy" }
))
.GetFormatter(Format.DateTime("yyyy-MM-dd HH:mm:ss", "MM/dd/yyyy"))
.SetFormatter(Format.DateTime("MM/dd/yyyy", "yyyy-MM-dd HH:mm:ss"))
)
.Field(new Field("AdvDeadline")
.Validator(Validation.DateFormat(
"MM/dd/yyyy",
new ValidationOpts { Message = "Please enter a date in the format MM/dd/yyyy" }
))
.GetFormatter(Format.DateSqlToFormat("MM/dd/yyyy"))
.SetFormatter(Format.DateFormatToSql("MM/dd/yyyy"))
)
.Field(new Field("TitleOfAdv"))
.Field(new Field("ListPrice"))
.Process(request)
.Data();
return Json(response, JsonRequestBehavior.AllowGet);
}
}
I could not figure it out after a long search. Anyone had the same issue? Any solution?
Check Out moment.js (https://momentjs.com), download moment-with-locales.js and add it to your ScriptBundle in BundleConfig.cs.
Then in your datatable's javascript code you can render the column in proper date/time format as follows. Note: my locale is 'pt' (Portugal). The date column is rendered as dd/mm/yyyy hh:mm (once again, see the formatting options in https://momentjs.com).
"columns": [
{ "data": "OriginName" },
{ "data": "SmsID" },
{ "data": "DestinationNumber" },
{
"data": "SMSDeliveryDate",
"render": function (data) {
var re = /-?\d+/;
var m = re.exec(data);
var d = new Date(parseInt(m[0]));
moment.locale('pt');
var m = moment(d).format('L LTS');
return m;
}
},
{ "data": "SmsStateDesc" }
],
Hope this info can be useful. I too was stuck with this for a few hours...
José
I had the same problem and eventually found the answer on the Editor forum.
If you look with fiddler (a great tool for seeing what happens) you
see the JSON has this format you get. If you look in the code in
visual studio express and capture what you got before passing it to
JSON you see something like "{12/12/2012 12:12}". So actually the
cause is the JSON.
Refactoring to just the essentials in your first column it should read like this.
This approach solved my problem without any problem. This version is designed to render null dates as blanks, otherwise format as directed. (Update: refactored the answer again, seeing that the next morning the formatted codes were not behaving as expected.)
{
data: "AdvStartDate",
render: function (data, type, full) {
if (data != null) {
var dtStart = new Date(parseInt(data.substr(6)));
return dtStart.toLocaleDateString();
} else {
return "";
}
}
Related
My goal is to create a column highchart that shows the name of various salesman and how much they have sold. I wrote this code to return from my SQL Database the names and the sum of the sales for each salesman:
[HttpPost]
public JsonResult ChartVendedores()
{
//Retorna um JSON contendo o nome do vendedor e o valor por ele vendido, usando inner join pelo id do vendedor.
try
{
var resultado = (from ve in db.tblVendedor
join vn in db.tblVenda on ve.vendedor_id equals vn.vendedor_id
group vn by new
{
ve.vendedor_nome
}into g
select new {
vendedor_nome = g.Key.vendedor_nome,
venda_valor = g.Sum(x => x.venda_valor)
}).ToList();
var jsonResult = new
{
Nomes = resultado.Select(x => x.vendedor_nome),
Valores = resultado.Select(x => x.venda_valor)
};
return Json(resultado);
}catch(Exception)
{
return null;
}
}
And this is where the chart is created, the method is called and it is suposed to fill the chart with the database's return data:
<script>
$(function () {
$.ajax({
url: '/Vendedores/ChartVendedores',
type: 'post',
async: false,
sucess: function (data) {
//Constrói o gráfico com os valores retornados pelo banco.
Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: 'Venda dos Colaboradores'
},
xAxis: {
categories: [
data.Nomes
],
crosshair: true
},
yAxis: {
min: 0,
title: {
text: 'Valor (R$)'
}
},
tooltip: {
headerFormat: '<span style="font-size:10px">{point.key}</span><table>',
pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' +
'<td style="padding:0"><b>{point.y:.1f} mm</b></td></tr>',
footerFormat: '</table>',
shared: true,
useHTML: true
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}
},
series: [{
name: 'Valores',
data: data.Valores
}]
});
}
})
})
What am I'm missing? As long as code goes, i don't think I wrote any wrong code in the method. Am I calling it wrong? Am I manipulating it wrong? I tried to remove my Ajax code, only leaving the chart itself as it is on the highchart.com and it worked, so the problem is not on my container div or in the chart code.
EDIT: As commented bellow, I looked at my console and I'm getting an warning about one of the imports that Highcharts needs. The waning follows is this one. After seeing this, I tried to remove the AJax and only using the highchart code. It worked! For some reason when the chart tries to use this:
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
It does not find it when the chart code is contained inside sucess: function(data){}
Note: I'm importing everything at the beggining of the code, meanwhile the script containing the Ajax is written last.
$.ajax({
url: '/Vendedores/ChartVendedores',
type: 'post',
async: false,
sucess: function (data) {
should be changed to:
$.ajax({
url: '/Vendedores/ChartVendedores',
type: 'post',
async: false,
success: function (data) {
You have misspelt success.
look at this, you are using return(resultado), but your json object to be returned is jsonResult , so use this:
var resultado = (from ve in db.tblVendedor
join vn in db.tblVenda on ve.vendedor_id equals vn.vendedor_id
group vn by new
{
ve.vendedor_nome
}into g
select new {
vendedor_nome = g.Key.vendedor_nome,
venda_valor = g.Sum(x => x.venda_valor)
}).ToList();
var jsonResult = new
{
Nomes = resultado.Select(x => x.vendedor_nome),
Valores = resultado.Select(x => x.venda_valor)
};
return Json(jsonResult);
Please test and let me know if it works :)
for (var i in data) {
// Add some text to the new cells:
cell1.innerHTML = data[i].Nomes ;
cell2.innerHTML = data[i].Valores ;
}
I have a datatable i wish to use defer render on, I am not sure what the issue is, my controller method returns an array of json objects. See code below.
**Datatable setup **
This is called when the page is loaded.
var $dtTable = $("#tblPlayer");
$dtTable.dataTable({
bFilter: false,
pageLength: 10,
paging: true,
autoWidth: true,
columns:
[
null,
{ "orderDataType": "dom-text", type: "string" },
{ "orderDataType": "dom-text", type: "string" },
{ "orderDataType": "dom-text-numeric" },
{ "orderDataType": "dom-text-numeric" },
{ "orderDataType": "dom-text-numeric" },
{ "orderDataType": "dom-text-numeric" },
{ "orderDataType": "dom-text-numeric" },
null,
null,
null
],
"ajax": "Player/GetSetPlayers",
"deferRender": true
});
Controller methods
public object[] GetSetPlayers()
{
var players = GetPlayers();
_players = new object[players.Count];
for (var i = 0; i < players.Count; i++)
{
_players[i] = players[i];
}
return _players;
}
GetSetPlayers() returns an array of json objects, the result below is an exampel of what index 0 and 1 will contain.
Response
[
{
"product":25000,
"rank":1,
"dirty_money":25000,
"id":"b4b41b18edbb49b9ae80be5e768b6b80",
"name":"Dan",
"ban_status":0,
"edit":"<a href='/support/player_gamedata/b4b41b18edbb49b9ae80be5e768b6b80/game' class='btn'><i class='icon-folder-close'></i></a>",
"credit":30,
"clean_money":20000,
"ban":"<a href='/support/ban_player/by_id/b4b41b18edbb49b9ae80be5e768b6b80/' class='btn'><i class='icon-remove'></i></a>",
"supplies":25000
},
{
"product":25000,
"rank":1,
"dirty_money":25000,
"id":"3cac6e366170458686021eaa77ac4d6d",
"name":"Dan",
"ban_status":0,
"edit":"<a href='/support/player_gamedata/3cac6e366170458686021eaa77ac4d6d/game' class='btn'><i class='icon-folder-close'></i></a>",
"credit":30,
"clean_money":20000,
"ban":"<a href='/support/ban_player/by_id/3cac6e366170458686021eaa77ac4d6d/' class='btn'><i class='icon-remove'></i></a>",
"supplies":25000
}
]
I think you need to specify a "data" attribute on each column that needs to be populated from the returned data. Otherwise it doesn't know what attribute on the json object goes to each column. If you defined your data as an array of arrays instead of an array of objects this wouldn't be required.
Additionally you aren't specifying a "dataSrc" option which isn't required but if it isn't set I believe it expects the returned JSON to be of the form:
{
data: [ {...}, {...} ]
}
So it would be helpful if you could add in the raw response to the ajax request.
EDIT1:
Ok so double checked and yes it does want an object array assigned to the "data" attribute on the JSON object so you can do something like this to fix this without having to modify anything on the server. Just change your ajax option to this:
"ajax": {
"url": "Player/GetSetPlayers",
"dataSrc": function ( json ) {
// We need override the built in dataSrc function with one that will
// just return the object array instead of looking for a "data"
// attribute on the "json" object. Note if you ever want to add
// serverside sorting/filtering/paging you will need to move your table
// data to an attribute within the JSON object.
return json;
}
}
So you will probably be good once you do both of the fixes above.
I have a report which generates chart.I am showing this report on pre defined data set.
First Image is from chrome browser.Second is from firefox.Firefox shows the correct data. But chrome is showing incorrect. you can see the month order.
I went through This question in StackOverflow.
still I got the result similar to first image.
anyone came up with these sort of issue ??
setDataSource: function (jsonData) {
myDataSource = new kendo.data.DataSource({
data: jsonData,
group: [{ "field": "Series" }],
sort: [{ "field": "Series", dir: "asc" }, { "field": "SortOrder", dir: "asc" }],
schema: {
model: {
fields: {
Category: {
"type": "string"
},
Series: {
"type": "number"
},
Value: {
"type": "number"
}
}
}
}
});
},
setupChart: function (id) {
$("#chart" + id).kendoChart({
dataSource: myDataSource,
title: {
text: "#Lables.LBL_PlanningProjection"
},
legend: {
position: "top"
},
chartArea: {
background: ""
},
seriesDefaults: {
type: "line"
},
series: [{
field: "Value"
}],
valueAxis: {
labels: {
format: "{0:N0}"
},
line: {
visible: true
},
majorUnit: 10000
},
categoryAxis: {
field: "Category",
labels: {
template: "#: value #",
rotation: 0
},
majorGridLines: {
visible: false
}
},
tooltip: {
visible: true,
format: "{0}",
template: "#= series.name #: #= value #"
}
});
}
This is a problem occurs with Chrome's implementation of Array.sort;
You can fix it by sorting the data source explicitly here.
And as I can see in your code, there is a field named SortOrder here. I think in the original code that you have get this, used that field to sort the dataset explicitly.
Check your Controller or Back-End code inorder to find the SortOrder property. If not you can add that in your back-end logic to sort your dataset explicitly according to the month order.
As I can see you can't do a explicit sort here by adding following line.
sort: [{ "field": "Series", dir: "asc" }, { "field": "Category", dir: "asc" }],
Because it 'll get your data set sorted as the first image.
Apr , Aug, Dec , Feb , Jan , Jul , Jun, Mar , May, Nov , Oct, Sep
I think that's why the original code has a property called SortOrder.
I have searched high and low for this problem... and I found a lot of people have the same problem but none have a definite solution...
Basically I have a grid on extjs... it gets data from sqldb. It loads fine using json. "But"... when trying to implement paging, this is where it gets messy...
pagesize is set to 5... which means first page should only show 5 records, but my grid shows the entire records
Even though the "next" button exists, it does not work technically because the entire record is already there on the first page
I set page.loadPage(2)... and the message says "Displaying Second Page", but it's actually displaying the entire records
The page number in "Page _ of 6" is always blank. see below image...
Below is my store...
var store = Ext.create('Ext.data.Store', {
storeId: 'myData',
pageSize: 5,
autoLoad: true,
method: "POST",
remoteSort: true,
fields: [
{ name: 'Q1', type: 'int' },
{ name: 'Q2', type: 'int' },
{ name: 'Q3', type: 'int' },
{ name: 'Q4', type: 'int' },
{ name: 'Q5', type: 'int' },
{ name: 'Improvements', type: 'string' },
{ name: 'Comments', type: 'string' }
],
sorters: [
{
property: 'Q1',
direct: 'ASC'
}
],
proxy: {
type: 'ajax',
url: 'GridView/writeRecord',
reader: {
type: 'json',
totalProperty: "count",
root: "myTable"
}
},
autoLoad: { params: { start: 0, limit: 5} }
});
this.grid = Ext.create('Ext.grid.Panel', {
title: ' ',
trackMouseOver: true,
disableSelection: true,
autoHeight: true,
store: store,
loadMask: true,
height: 500,
width: 800,
renderTo: Ext.getBody(),
columns: [
{ header: 'Q1',
sortable: true, dataIndex: 'Q1'
},
{ header: 'Q2',
sortable: true, dataIndex: 'Q2'
},
{ header: 'Q3',
sortable: true, dataIndex: 'Q3'
},
{ header: 'Q4',
sortable: true, dataIndex: 'Q4'
},
{ header: 'Improvements', flex: 1,
sortable: true, dataIndex: 'Improvements'
},
{ header: 'Comments', flex: 1,
sortable: true, dataIndex: 'Comments'
}
],
bbar: Ext.create('Ext.PagingToolbar', {
store: store,
displayInfo: true,
preprendButtons: true,
displayMsg: 'Displaying Surveys {0} - {1} of {2}',
emptyMsg: "No Surveys to display"
})
});
and this is my JSON... it has actually 30 records but I trimmed it down...
{
"count": 30,
"myTable": [
{
"Q1": "1",
"Q2": "1",
"Q3": "1",
"Q4": "1",
"Improvements": "",
"Comments": "1"
},
{
"Q1": "3",
"Q2": "2",
"Q3": "2",
"Q4": "2",
"Improvements": "This is A very long comment. What do you think?",
"Comments": "Agreed"
},
{
"Q1": "4",
"Q2": "2",
"Q3": "4",
"Q4": "3",
"Improvements": "Hello2",
"Comments": "Hello2"
},
{
"Q1": "3",
"Q2": "2",
"Q3": "2",
"Q4": "1",
"Improvements": "Hello4",
"Comments": "Hello4"
}
]
}
Also if it helps this is how I get my Json
string sqlquery = "SELECT Q1, Q2, Q3, Q4, Improvements, Comments FROM ITable";
conn.Open();
SqlDataAdapter cmd = new SqlDataAdapter(sqlquery, conn);
SqlCommand comd = new SqlCommand(sqlquery, conn);
DataSet myData = new DataSet();
cmd.Fill(myData, "myTable");
comd.CommandText = "SELECT COUNT(*) FROM ITable";
Int32 count = (Int32)comd.ExecuteScalar();
comd.ExecuteNonQuery();
conn.Close();
var results = (new
{
TotalNumber = count,
myTable = myData
});
return JsonConvert.SerializeObject(new { count=count, myTable = myData.Tables[0] }, Formatting.Indented,
new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
I know my Json is right... and it reads 30 records because is says "Displaying _ of 30"... I just have no clue what I am doing wrong... It cannot be a browser issue... why is it throwing up all in one page? anybody?
When using the paging toolbar, the server is supposed to page the data for you. You don't feed it all of the records at once.
The paging toolbar will send requests asking for each page, and the server is supposed to return just the records for that page.
If you want to page with in memory data (fetching them all at once, you have to implement your own, or use one of the extensions.
See the section titled "Paging with Local Data" at http://docs.sencha.com/ext-js/4-1/#!/api/Ext.toolbar.Paging
Therefore, to use it as intended, you have to change your server code to account for the start and limit HTTP parameters
I have posted question here and answer is correct but I'm was not perfectly clear. On the init page load everything is ok, but I need to call with date parameter as argument.
So this is fine
$('#myDate').click(function () {
var date = getDate();
})
but I should send this date to
$('#dataTable').dataTable({
...
Update
Ok, I'm simplifying this,
$('#dataTable').dataTable({
...
on page load takes myDate value and sends this value to the controller. This is fine. Problem is when after page load user pick some other date, I want again to send this data value to the $('#dataTable').dataTable({..
Hope this helps, thanks
function getDate() {
var date = $('input[name="myDate"]').val();
return date;
};
$('#myDate').click(function () {
var date = getDate();
return date;
});
$('#dataTable').dataTable({
"bServerSide": true,
"sAjaxSource": "/Home/Ajax",
"fnServerParams": function (aoData) {
var date = getDate();
aoData.push({ "name": "myDate", "value": date });
},
Maybe something like this?
function getDate() {
var date = $('input[name="myDate"]').val();
return date;
}
$('#myDate').click(updateDate);
function updateDate() {
$('#dataTable').dataTable({
"bServerSide": true,
"sAjaxSource": "/Home/Ajax",
"fnServerParams": function (aoData) {
var date = getDate();
aoData.push({ "name": "myDate", "value": date });
},
//... I assume there's more
}
updateDate();