簡體   English   中英

使用Asp.Net MVC和KnockoutJS處理日期

[英]Handling dates with Asp.Net MVC and KnockoutJS

我最近開始使用KnockoutJs並很快意識到使用默認的Json(myModelWithADate)導致默認的json編碼為\\/Date(-62135578800000)\\/通過一些研究我找到了四種可能的方法來處理我的日期顯示dom元素。

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) {

    }
};

用法

<td data-bind="date: DueDate">
</td>

2)從控制器返回“字符串”

return Json(new {MyDate = DateTime.Now.ToShortDateString()});

3)使用JSON.NET指定在james.newtonking.com上看到的日期時間格式

string isoJson = JsonConvert.SerializeObject(entry, new IsoDateTimeConverter());
// {"Details":"Application started.","LogDate":"2009-02-15T00:00:00Z"}

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;
});

他們似乎都工作,但我仍然在努力與哪一個感覺“正確”。 現在,我的內心正在與綁定和返回的字符串混合。 正如我可以看到自己擴展綁定以使用jQuery UI datepicker控件處理輸入。

處理顯示日期或其他類型(如貨幣)時是否有可接受的做法? 我還缺少另一個可以解決這個問題的選擇嗎?

我個人認為JSON.NET解決方案是最好的,因為它對客戶端的影響較小。 所有其他解決方案都需要額外的客戶端解析或其他客戶端代碼。

我已經切換到使用JSON.NET來使用所有使用JSON的ASP .NET代碼,因為它是一個更可定制的庫。

例如,我必須在MVC中實現符合Google的Chart API (與Knockout結合用於分頁等)的JSON數據,而默認的JavascriptSerializer根本無法做到。

除了JSON.NET,你可以自定義它以實際吐出完整的Knockout視圖模型,這樣你甚至不需要使用映射插件。

我寫了一個名為FluentJson.NET的示例庫,它允許您在Razor中執行以下操作:

var viewModel = @JsonObject.Create()
    .AddProperty("name", "value")
    .AddObservable("knockoutProperty", 123)

得到:

var viewModel = {"name":"value","knockoutProperty":ko.observable(123)}

因此,您可以獲得一個Knockout視圖模型,而無需任何客戶端箍跳過。

你可以輕松地擴展這樣的東西來處理日期值,但你更喜歡。

我建議通過ko.mapping.fromJS( data, mapping )的中間人方法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參數允許您輕松處理更改,也可以輕松地使用數組。

在knockoutjs中處理日期的更好方法是使用時刻庫​​並處理像boss這樣的日期。 您可以輕松處理/ Date(-62135578800000)/等日期。 無需擔心控制器中序列化日期的方式。

方法1:直接在視圖中:

讓我們說你的淘汰模型在一個名為sentDate的可觀察對象中得到這樣的日期,現在它有值/日期(-62135578800000)/。 要在視圖中綁定它,您可以:

<p><label>Date</label>: <span data-bind="moment(sentDate).format('MM/DD/YYYY')"></span></p>

方法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) {

    }
};

用法和你說的一樣:

<td data-bind="date: sentDate">
</td>

momentjs支持日期上的大量日期時間格式和實用程序功能。

我正在使用以下代碼生成短日期字符串。 我將它用於我的日期字符串和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);
    }

這會生成以下JSON

"{"d":"4/21/2012"}"

這樣可以為我提供干凈的JavaScript代碼。

剛剛提出這個問題,因為我們也開始在我們的MVC3應用程序上使用knockout.js。 由於我們已經有了jQuery datepicker,我們需要通過locale以不同的方式格式化日期(門戶網站有不同的語言,每種語言都有不同的格式),所以也許這個技術要求的混搭會出現在其他地方,並且會很有用:

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) {
    }
};

然后在視圖中,例如:

<p><label>Date</label>: <span data-bind="date: SentDate"></span></p>

@ photo_tom答案的一個更清晰的替代方法是通過JsonConverter屬性使用IsoDateTimeConverter來裝飾屬性,如下所示:

public class MyClass
{
    [JsonConverter(typeof(IsoDateTimeConverter))]
    public DateTime Timestamp { get; set; }
}

我喜歡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);

我總是使用數據轉換器而不是直接向服務器發送數據來修復任何客戶端編碼或解析問題,而無需使用其他工具。

在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;
};

然后我使用dataConverter而不是視圖模型中的ajax save方法中的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
            }
        });
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM