web-dev-qa-db-ja.com

Asp.NetMVCとKnockoutJSを使用した日付の処理

私は最近KnockoutJsでの作業を開始し、デフォルトのJson(myModelWithADate)を使用するとすぐに\/Date(-62135578800000)\/のデフォルトのjsonエンコーディングが得られることに気付きました。少し調べて、日付の表示を処理する4つの方法を見つけました。 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 answer。

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

それらはすべて機能しているように見えますが、私はまだ「正しい」と感じるものに苦労しています。今、私の腸は、バインディング文字列とリターン文字列を組み合わせて使用​​しています。 jQueryUIのdatepickerコントロールで入力を処理するようにバインディングを拡張していることがわかりました。

日付や通貨などの他のタイプの表示を処理するときに受け入れられる慣行はありますか?この問題を解決するために私が見逃している別のオプションはありますか?

30
Mark Coleman

個人的には、 JSON.NET ソリューションは、クライアントへの負担が少ないという理由だけで最適だと思います。他のすべてのソリューションでは、追加のクライアント解析または追加のクライアントコードが必要です。

はるかにカスタマイズ可能なライブラリであるため、JSONを使用するすべてのASP .NETコードにJSON.NETを使用するように切り替えました。

たとえば、 GoogleのChart API (ページングなどのためにKnockoutと組み合わせて使用​​)に準拠したJSONデータをMVCに実装する必要があり、デフォルトのJavascriptSerializerでは実装できません。

さらに、JSON.NETをカスタマイズして、完全なノックアウトビューモデルを実際に吐き出すことができるため、マッピングプラグインを使用する必要もありません。

FluentJson.NET というサンプルライブラリを作成しました。これにより、Razorで次のようなことができます。

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

そして取得:

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

したがって、クライアント側のフープを飛び越えることなく、ノックアウトビューモデルを取得できます。

そのようなものを簡単に拡張して、日付の値を処理することができます。

13
Paul Tyng

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

マッピングパラメータを使用すると、変更を簡単に処理でき、配列でも簡単に活用できます。

6
Andres Toro

Knockoutjsで日付を処理するためのより良い方法は、モーメントライブラリを使用し、ボスのように日付を処理することです。/Date(-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 日付に関する多くの日時形式とユーティリティ関数をサポートします。

5
Ajay Kelkar

@photo_tomの答えのよりクリーンな代替手段は、次のように、JsonConverter属性を介してIsoDateTimeConverterでプロパティを装飾することです。

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

MVC3アプリでもknockout.jsを使い始めたので、この質問に出くわしました。すでにjQuerydatepickerがあり、ロケールごとに異なる形式で日付をフォーマットする必要があるため(ポータルには異なる言語があり、言語ごとに異なる形式が表示されます)、この技術要件のマッシュアップは別の場所で発生し、役立つ可能性があります。

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
povilasp

次のコードを使用して、短い日付文字列を生成しています。日付文字列と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コードが得られます。

2
photo_tom

追加のツールを使用せずに、クライアントのエンコードや解析の問題を修正するために、データをサーバーに直接送信する代わりに、常にデータコンバーターを使用しています。

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

次に、ビューモデル内の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
            }
        });
    }
0
Ashraf Abusada

私の場合、入力フィールドがフォーマットされた文字列を期待していることを除いて、AndresToroの答えが気に入りました。だから私は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);
0
Ashi