Обработка дат с помощью Asp.Net MVC и KnockoutJS - PullRequest
30 голосов
/ 05 января 2012

Я недавно начал работать с 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;
});

Кажется, все они работают, но я все еще борюсь с тем, кто чувствует себя "правильным". Прямо сейчас мой кишечник идет со смесью со связывающими и возвращающими строками. Как я мог видеть, я расширяю привязку для обработки ввода с помощью элементов управления DatePicker пользовательского интерфейса jQuery.

Есть ли общепринятая практика при обработке отображения дат или других типов, таких как валюта? Есть ли другой вариант, который мне не хватает, чтобы решить эту проблему?

Ответы [ 8 ]

13 голосов
/ 05 января 2012

Лично я считаю, что решение JSON.NET является лучшим просто потому, что оно навязывает клиенту меньше.Все остальные решения требуют дополнительного разбора клиента или дополнительного клиентского кода.

Я перешел на использование JSON.NET для всего моего кода ASP .NET, который использует JSON, потому что это гораздо более настраиваемая библиотека.

Например, мне пришлось реализовать данные JSON в MVC, которые соответствовали Google Chart API (используется в сочетании с Knockout для пейджинга и т. Д.), И значение по умолчанию JavascriptSerializer просто не может сделатьit.

В дополнение к 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 безПрыжки через клиентскую область.

Вы можете легко расширить что-то подобное, чтобы обрабатывать значения даты, как вам бы хотелось.

6 голосов
/ 27 марта 2012

Я бы предложил подход среднего человека через 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 );

параметр отображения позволяет легко обрабатывать изменения и может быть легко использован с массивами.

5 голосов
/ 06 июля 2014

Лучший способ обрабатывать даты в knockoutjs - использовать библиотеку моментов и обрабатывать даты, как босс. Вы можете легко иметь дело с датами, такими как / Дата (-62135578800000) /. Не нужно беспокоиться о том, как ваша дата сериализации в контроллере.

Подход 1: Прямо в поле зрения:

Допустим, ваша модель выбивания получает такую ​​дату в наблюдаемой области с именем sentDate и теперь имеет значение / Date (-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 поддерживает множество форматов даты и времени и функции полезности для дат.

2 голосов
/ 01 сентября 2013

Более чистая альтернатива ответу @ photo_tom - украсить свойство с помощью IsoDateTimeConverter через атрибут JsonConverter, например:

public class MyClass
{
    [JsonConverter(typeof(IsoDateTimeConverter))]
    public DateTime Timestamp { get; set; }
}
2 голосов
/ 06 декабря 2012

Только что пришел к этому вопросу, потому что мы также начали использовать knockout.js в нашем приложении MVC3. Поскольку у нас уже есть jQuery datepicker, и нам нужно форматировать даты по-разному в зависимости от локали (у портала разные языки и разные форматы представлены для каждого языка), так что, возможно, это сочетание технологических требований возникнет где-то еще и будет полезно:

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>
2 голосов
/ 22 апреля 2012

Я использую следующий код для генерации коротких строк даты. Я использую его для своих строк дат и JQueryUi Date Picker.

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 для меня.

0 голосов
/ 31 января 2019

Я всегда использую конвертер данных вместо того, чтобы отправлять данные непосредственно на сервер, чтобы исправить любые проблемы с кодировкой или синтаксическим анализом клиента, без необходимости использования дополнительных инструментов.

В файле модели представления Knockout JS я добавляю следующий код перед настройкой модели представления, который перехватывает выбранные объекты модели представления и использую 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 вместо data в методе сохранения Ajax в модели представления:

// 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
            }
        });
    }
0 голосов
/ 22 мая 2017

Мне понравился ответ Андреса Торо, за исключением того, что в моем случае поля ввода ожидают отформатированные строки. Поэтому я использую 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...