javascript 使用 Asp.Net MVC 和 KnockoutJS 处理日期
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8735617/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Handling dates with Asp.Net MVC and KnockoutJS
提问by Mark Coleman
I recently started working with KnockoutJs and quickly realized using the default Json(myModelWithADate)
resulted in the default json encoding of \/Date(-62135578800000)\/
With a bit of research I located four potential ways to handle the display of my dates in dom elements.
我最近开始使用 KnockoutJs 并很快意识到使用默认会Json(myModelWithADate)
导致默认的 json 编码\/Date(-62135578800000)\/
通过一些研究,我找到了四种可能的方法来处理我的日期在 dom 元素中的显示。
1) Create a binding that handles the conversion from the Json date to the format you desire
1) 创建一个绑定来处理从 Json 日期到您想要的格式的转换
ko.bindingHandlers.date = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var jsonDate = valueAccessor();
var value = new Date(parseInt(jsonDate.substr(6)));
var ret = value.getMonth() + 1 + "/" + value.getDate() + "/" + value.getFullYear();
element.innerHTML = ret;
},
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
}
};
Usage
用法
<td data-bind="date: DueDate">
</td>
2) Return “strings” from your Controller
2)从你的控制器返回“字符串”
return Json(new {MyDate = DateTime.Now.ToShortDateString()});
3) Use the JSON.NET to specify a Date Time format seen over at james.newtonking.com
3) 使用 JSON.NET 指定在james.newtonking.com 上看到的日期时间格式
Example
例子
string isoJson = JsonConvert.SerializeObject(entry, new IsoDateTimeConverter());
// {"Details":"Application started.","LogDate":"2009-02-15T00:00:00Z"}
4) use JSON.parse to handle your dates as seen in this stackoverflow answer.
4) 使用 JSON.parse 来处理您的日期,如此stackoverflow 答案所示。
JSON.parse(jsonText, function(key, value) {
// Check for the /Date(x)/ pattern
var match = /\/Date\((\d+)\)\//.exec(value);
if (match) {
var date = new Date(+match[1]); // Convert the ticks to a Date object
return humanReadable(date); // Format the date how you want it
}
// Not a date, so return the original value
return value;
});
They all appear to work, but I am still struggling with which one feels “right”. Right now my gut is going with a mix with the binding and returning strings. As I could see myself extending the binding to handle input with jQuery UI datepicker controls.
它们似乎都有效,但我仍在为哪个感觉“正确”而苦苦挣扎。现在我的直觉是将绑定和返回字符串混合在一起。正如我所看到的,我使用 jQuery UI 日期选择器控件扩展了绑定以处理输入。
Is there an accepted practice when handling displaying dates or other types such as currency? Is there another option I am missing that solves this problem?
处理显示日期或其他类型(例如货币)时是否有公认的做法?我是否缺少解决此问题的另一种选择?
采纳答案by Paul Tyng
Personally I think the JSON.NETsolution is the best simply because it imposes less on the client. All the other solutions require additional client parsing or additional client code.
我个人认为JSON.NET解决方案是最好的,因为它对客户端的影响较小。所有其他解决方案都需要额外的客户端解析或额外的客户端代码。
I have switched over to using JSON.NET for all of my ASP .NET code that uses JSON because its a much more customizable library.
对于使用 JSON 的所有 ASP .NET 代码,我已切换到使用 JSON.NET,因为它是一个更加可定制的库。
For example I have had to implement JSON data in MVC that conformed to Google's Chart API(used in combination with Knockout for paging, etc.) and the default JavascriptSerializer
simply cannot do it.
例如,我不得不在符合Google Chart API 的MVC 中实现 JSON 数据(与 Knockout 结合使用以进行分页等),默认情况下JavascriptSerializer
根本无法做到。
In addition with JSON.NET you can customize it to actually spit out full Knockout view models so you don't even need to employ the mapping plugin.
此外,使用 JSON.NET,您可以自定义它以实际输出完整的 Knockout 视图模型,因此您甚至不需要使用映射插件。
I wrote a sample library called FluentJson.NETwhich lets you do things in Razor like:
我编写了一个名为FluentJson.NET的示例库,它可以让您在 Razor 中执行以下操作:
var viewModel = @JsonObject.Create()
.AddProperty("name", "value")
.AddObservable("knockoutProperty", 123)
And get:
并得到:
var viewModel = {"name":"value","knockoutProperty":ko.observable(123)}
So you can get a Knockout view model without any client side hoops to jump through.
因此,您可以获得一个 Knockout 视图模型,而无需跳过任何客户端箍。
You could easily extend something like that to handle date values however you would prefer.
您可以轻松地扩展类似的东西来处理您喜欢的日期值。
回答by Andres Toro
I would suggest a middle man approach through ko.mapping.fromJS( data, mapping )
this would allow you to customize even with a user defined object.
我建议通过ko.mapping.fromJS( data, mapping )
这种中间人方法 ,即使使用用户定义的对象也可以进行自定义。
var $data = { _ID : '1', _Created : someDate };
var $mapping = {
'_Created' : {
update: function (options) {
return convertdata( options.data );
}
}
}
var viewDataModel = ko.mapping( data, mapping );
ko.applyBindings( viewDataModel );
mapping parameter allows you handle changes easily and can easily be leveraged with arrays also.
mapping 参数允许您轻松处理更改,并且也可以轻松地与数组一起使用。
回答by Ajay Kelkar
The better way to handle dates in knockoutjs is to use moment library and handle dates like boss. You can easily deal with dates like /Date(-62135578800000)/. No need to bother of how your serialize date in controller.
在knockoutjs 中处理日期的更好方法是使用moment 库并像boss 一样处理日期。您可以轻松处理 /Date(-62135578800000)/ 之类的日期。无需担心您在控制器中如何序列化日期。
Approach 1 : Directly in view:
方法一:直接查看:
Lets say your knockout model gets such date in a observable called sentDate and now it has value /Date(-62135578800000)/. To bind it in view you can do :
假设您的淘汰赛模型在名为 sentDate 的 observable 中获得这样的日期,现在它具有值 /Date(-62135578800000)/。要在视图中绑定它,您可以执行以下操作:
<p><label>Date</label>: <span data-bind="moment(sentDate).format('MM/DD/YYYY')"></span></p>
Approach 2 : In custom binding
方法 2:在自定义绑定中
ko.bindingHandlers.date = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var jsonDate = valueAccessor();
var ret = moment(jsonDate).format('MM/DD/YYYY');
element.innerHTML = ret;
},
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
}
};
Usage same as you had said :
用法和你说的一样:
<td data-bind="date: sentDate">
</td>
momentjssupports lots of date time formats and utility functions on dates.
momentjs支持许多日期时间格式和日期实用程序功能。
回答by photo_tom
I'm using the following code to generate short date strings. I use it for my date strings and jQueryUi Date Picker.
我正在使用以下代码生成短日期字符串。我将它用于我的日期字符串和 jQueryUi 日期选择器。
class T
{
public DateTime d { get; set; }
}
static void Main(string[] args)
{
var k = new T { d = DateTime.Now };
var formatter = new IsoDateTimeConverter();
formatter.DateTimeFormat = "d";
var s = JsonConvert.SerializeObject(k, formatter);
}
This generates the following JSON
这将生成以下 JSON
"{"d":"4/21/2012"}"
This results clean JavaScript code for me.
这对我来说是干净的 JavaScript 代码。
回答by povilasp
Just came up on this question because we also started using knockout.js on our MVC3 app. Since we already have jQuery datepicker and we need to format dates differently by locale (portal has different languages and different formats are presented per language), so maybe this mashup of technological requirements arise somewhere else and will be useful:
刚刚提出这个问题是因为我们也开始在我们的 MVC3 应用程序上使用 Knockout.js。由于我们已经有了 jQuery 日期选择器,我们需要按地区设置不同的日期格式(门户网站有不同的语言,并且每种语言呈现不同的格式),所以也许这种技术要求的混搭出现在其他地方并且会有用:
var jsDateFormat = "@CultureHelper.JsDateFormat"; // can be something like yy-mm-dd
//...
ko.bindingHandlers.date = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor();
if (value != null) {
var jsonDate = new Date(parseInt(valueAccessor().substr(6)));
element.innerHTML = jQuery.datepicker.formatDate(jsDateFormat, jsonDate);
}
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
}
};
And in the view then for example:
然后在视图中例如:
<p><label>Date</label>: <span data-bind="date: SentDate"></span></p>
回答by Jess Chadwick
A cleaner alternative to @photo_tom's answer is to decorate the property with the IsoDateTimeConverter via the JsonConverter attribute, like so:
@photo_tom 答案的一个更简洁的替代方法是通过 JsonConverter 属性使用 IsoDateTimeConverter 装饰属性,如下所示:
public class MyClass
{
[JsonConverter(typeof(IsoDateTimeConverter))]
public DateTime Timestamp { get; set; }
}
回答by Ashi
I loved Andres Toro's answer except that in my case, input fields are expecting formatted strings. So I am using JQuery to format my dates according to my favorite format provided by my helper @Html.ConvertDateFormat()
Hope this helps someone day.
我喜欢 Andres Toro 的回答,只是在我的情况下,输入字段需要格式化的字符串。所以我使用 JQuery 根据我的助手提供的我最喜欢的格式来格式化我的日期@Html.ConvertDateFormat()
希望这对某人有帮助。
var mapping = {
'ActualDateTime': {
update: function (options) {
var d = /\/Date\((\d*)\)\//.exec(options.data);
return (d) ? $.datepicker.formatDate('@Html.ConvertDateFormat()', new Date(+d[1])) : value;
//return "5/10/2017";
}
}
};
var paymentModel = ko.mapping.fromJS(modelJSON, mapping);
回答by Ashraf Abusada
I always use a data converter instead of sending data directly to server to fix any client encoding or parsing issues, without the need to use additional tools.
我总是使用数据转换器而不是直接将数据发送到服务器来修复任何客户端编码或解析问题,而无需使用其他工具。
In the Knockout JS view model file, I add the following code before the view model setup, which intercept selected proeprries of the view model and use moment.jsto take care of date convertions:
在 Knockout JS 视图模型文件中,我在视图模型设置之前添加以下代码,它拦截视图模型的选定 proeprries 并使用moment.js处理日期转换:
// converting data before sending to controller
var dataConverter = function (key, value) {
if (key === 'InvoiceDate') {
return moment(value).format("YYYY MMMM DD");
}
return value;
};
Then I use the dataConverter
instead of data
in the ajax save method within the view model:
然后我在视图模型中的 ajax 保存方法中使用dataConverter
而不是data
:
// Example view model for sales invoice
SalesInvoiceViewModel = function (data) {
var self = this;
ko.mapping.fromJS(data, {}, self);
self.SaveInvoice = function () {
$.ajax({
url: '/SalesInvoices/SaveInvoice/',
type: 'POST',
data: ko.toJSON(self, **dataConverter**),
contentType: 'application/json',
success: function (data) {
if (data.invoiceViewModel !== null) {
ko.mapping.fromJS(data.invoiceViewModel, {}, self);
}
if (data.redirectToLocation !== null) {
window.location = data.redirectToLocation;
}
},
error: function (xhr, ajaxOptions, thrownError) {
// report error to user
}
});
}