it-swarm.com.de

Terminverwaltung mit Asp.Net MVC und KnockoutJS

Ich begann vor kurzem mit KnockoutJs zu arbeiten und stellte schnell fest, dass der Standardwert Json(myModelWithADate) die Standard-Json-Kodierung von \/Date(-62135578800000)\/ ergab. Mit ein wenig Recherche habe ich vier mögliche Wege gefunden, um die Anzeige meiner Datumsangaben in dom-Elementen zu behandeln.

1) Erstellen Sie eine Bindung, die die Konvertierung vom Json-Datum in das gewünschte Format vornimmt

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

    }
};

Verwendungszweck

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

2) Gib "Zeichenketten" von deinem Controller zurück

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

3) Verwenden Sie JSON.NET, um ein Datums-/Uhrzeitformat anzugeben, das unter james.newtonking.com zu sehen ist

Beispiel

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

4) Verwenden Sie JSON.parse, um Ihre Daten wie in dieser stackoverflow-Antwort zu behandeln.

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

Sie scheinen alle zu funktionieren, aber ich habe immer noch Schwierigkeiten, mit denen man sich "richtig" fühlt. Momentan geht es mir gut mit einer Mischung aus Bindung und wiederkehrenden Saiten. Wie ich sehen konnte, dehnte ich die Bindung aus, um Eingaben mit jQuery UI-Datepicker-Steuerelementen zu verarbeiten. 

Gibt es eine akzeptierte Vorgehensweise bei der Anzeige von Datumsangaben oder anderen Arten wie z. B. Währung? Gibt es eine andere Option, die ich vermisse, die dieses Problem löst?

30
Mark Coleman

Ich persönlich denke, dass die JSON.NET -Lösung die beste ist, weil sie dem Client weniger auferlegt. Alle anderen Lösungen erfordern zusätzliches Client-Parsing oder zusätzlichen Client-Code.

Ich habe auf die Verwendung von JSON.NET für meinen gesamten ASP .NET-Code umgestellt, der JSON verwendet, da es eine viel anpassbarere Bibliothek ist. 

Zum Beispiel musste ich JSON-Daten in MVC implementieren, die der Google Chart API (in Kombination mit Knockout für Paging usw.) entsprechen. Die Standardvariable JavascriptSerializer kann dies einfach nicht.

Darüber hinaus können Sie es mit JSON.NET so anpassen, dass es tatsächlich vollständige Knockout-Ansichtsmodelle ausspuckt, sodass Sie nicht einmal das Mapping-Plugin verwenden müssen.

Ich habe eine Beispielbibliothek namens FluentJson.NET geschrieben, mit der Sie Dinge in Razor wie folgt ausführen können:

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

Und bekomme:

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

So können Sie ein Knockout-Ansichtsmodell erhalten, ohne dass Sie auf der Seite eines Clients einen Sprung machen müssen.

Sie können so etwas auf einfache Weise erweitern, um Datumswerte zu verarbeiten, wie Sie möchten.

13
Paul Tyng

Ich würde vorschlagen, dass ein mittlerer Mann durch ko.mapping.fromJS( data, mapping ) vorgeht, wodurch Sie auch mit einem benutzerdefinierten Objekt anpassen können. 

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

mit dem Mapping-Parameter können Sie Änderungen einfach handhaben und auch mit Arrays problemlos genutzt werden. 

6
Andres Toro

Um Daten in knockoutjs besser zu behandeln, verwenden Sie die Momentbibliothek und behandeln Daten wie Boss. Sie können mit Datumsangaben wie/Date (-62135578800000)/umgehen. Sie müssen sich nicht darum kümmern, wie Ihr Datum im Controller serialisiert wird. 

Ansatz 1: Direkt im Blick:

Nehmen wir an, Ihr Knockout-Modell erhält ein solches Datum in einem Observable namens sentDate. Jetzt hat es den Wert/Date (-62135578800000) /. Um es in der Ansicht zu binden, können Sie Folgendes tun: 

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

Ansatz 2: In der benutzerdefinierten Bindung  

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

    }
};

Verwendung wie Sie es gesagt haben: 

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

momentjs unterstützt viele Datumszeitformate und Dienstfunktionen an Datumsangaben.

5
Ajay Kelkar

Eine sauberere Alternative zu @ photo_tom ist die Dekoration der Eigenschaft mit dem IsoDateTimeConverter über das JsonConverter-Attribut.

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

Ich kam gerade zu dieser Frage auf, weil wir auch begonnen haben, knockout.js in unserer MVC3-App zu verwenden. Da wir bereits jQuery datepicker haben, müssen wir Datumsangaben je nach Gebietsschema unterschiedlich formatieren (das Portal hat verschiedene Sprachen und unterschiedliche Formate.) Sprache), so kann diese Vermischung der technologischen Anforderungen woanders entstehen und nützlich sein:

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

Und in der Ansicht dann zum Beispiel:

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

Ich verwende den folgenden Code, um kurze Datumszeichenfolgen zu generieren. Ich verwende es für meine Datumsstrings und den 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);
    }

Dies generiert den folgenden JSON

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

Dies führt zu sauberem JavaScript-Code für mich.

2
photo_tom

Ich verwende immer einen Datenkonverter, anstatt Daten direkt an den Server zu senden, um Probleme mit der Codierung oder Analyse von Clients zu beheben, ohne dass zusätzliche Tools erforderlich sind.

In der Knockout-JS-Ansichtsmodelldatei füge ich vor dem Einrichten des Ansichtsmodells den folgenden Code hinzu, der ausgewählte Projekte des Ansichtsmodells abfängt und moment.js verwendet, um Datumsumwandlungen vorzunehmen:

// converting data before sending to controller
var dataConverter = function (key, value) {  
    if (key === 'InvoiceDate') {
        return moment(value).format("YYYY MMMM DD");
    }

    return value;
};

Dann verwende ich die dataConverter anstelle von data in der ajax save-Methode im Ansichtsmodell:

// 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

Ich habe die Antwort von Andres Toro geliebt, nur dass Eingabefelder in meinem Fall formatierte Zeichenfolgen erwarten. Also benutze ich JQuery, um meine Datumsangaben gemäß meinem Lieblingsformat zu formatieren, das von meinem Helfer @Html.ConvertDateFormat() Bereitgestellt wird. Hoffe, das hilft jemandem Tag.

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