2012-01-04 35 views
29

Recientemente comencé a trabajar con KnockoutJs y rápidamente me di cuenta de que usando el valor predeterminado Json(myModelWithADate) resultó en la codificación json predeterminada de \/Date(-62135578800000)\/ Investigué un poco cuatro formas posibles de manejar la visualización de mis fechas en elementos dom.Manejando fechas con Asp.Net MVC y KnockoutJS

1) Crear un enlace que se encarga de la conversión de la fecha de JSON para el formato que desee

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

    } 
}; 

Uso

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

2) Retorno “cadenas” de su controlador

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

3) Usar la JSON.NET para especificar un formato de Fecha Hora visto en más de james.newtonking.com

Ejemplo

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

4) utilizan JSON.parse para manejar sus fechas como se ve en este 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; 
}); 

Todos parecen funcionar, pero todavía estoy luchando con cuál se siente "bien". En este momento, mi intestino va con una mezcla con las cuerdas de unión y de retorno. Como pude ver, extendí el enlace para manejar la entrada con los controles jQuery UI datepicker.

¿Existe una práctica aceptada cuando se manejan fechas de visualización u otros tipos como la moneda? ¿Hay alguna otra opción que me falta que resuelva este problema?

+0

Uso cadenas en mis proyectos. El archivador modelo puede analizar una fecha de una cadena para que pueda redondear los valores de viaje fácilmente de esa manera. – Ryan

+0

He publicado mi resultado de json net para el mismo problema, convierte la fecha en formato iso, por lo que es mucho más fácil trabajar con él. http://stackoverflow.com/questions/15778599/knockout-dates-being-reset-on-post-to-mvc-controller/15799992#15799992 – Kieran

+0

El uso de momentjs es la mejor manera de lidiar con las fechas, ver mi respuesta a esto pregunta. –

Respuesta

12

Personalmente creo que la solución JSON.NET es la mejor simplemente porque impone menos en el cliente. Todas las demás soluciones requieren un análisis adicional del cliente o un código de cliente adicional.

He cambiado a usar JSON.NET para todo mi código ASP .NET que utiliza JSON porque es una biblioteca mucho más personalizable.

Por ejemplo, he tenido que aplicar los datos JSON en MVC que conformaron a Google's Chart API (utilizado en combinación con Knockout para paginación, etc.) y el valor por defecto JavascriptSerializer simplemente no pueden hacerlo.

Además, con JSON.NET puede personalizarlo para que escuche realmente modelos completos de vistas eliminatorias para que no tenga que utilizar el plugin de mapeo.

escribí una biblioteca de ejemplo denominado FluentJson.NET que le permiten hacer las cosas de la maquinilla de afeitar gustan:

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

y obtener:

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

para que pueda obtener un modelo de vista Knockout sin aros lado del cliente para saltar

Podría extender fácilmente algo así para manejar los valores de fecha como prefiera.

+0

Interesante proyecto de nuget, sin duda lo comprobaré. –

+0

Reemplacé mi Json.Encode (Modelo) al JSONConnect JsonConvert.SerializeObject (Modelo) por este motivo exacto. Funciona como un amuleto y no tuve que escribir ninguna otra línea de código. Buen consejo. He estado buscando esto todo el día. –

6

Sugeriría un enfoque de hombre medio a través de ko.mapping.fromJS(data, mapping) esto le permitiría personalizar incluso con un objeto definido por el usuario.

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

El parámetro de asignación le permite manejar cambios fácilmente y también puede ser aprovechado fácilmente con arreglos.

+0

La mejor solución: 1- no hay bibliotecas adicionales para agregar a su proyecto. 2- su código no atraviesa todos los campos; actualiza directamente los campos que especifique. El único problema aquí es que los campos de entrada realmente necesitan cadenas formateadas. – Ashi

2

Estoy usando el siguiente código para generar cadenas de fecha cortas. Lo uso para mis cadenas de fechas y 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); 
    } 

Esto genera el siguiente JSON

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

Esto se traduce el código JavaScript limpia para mí.

2

Acabo de llegar a esta pregunta porque también comenzamos a utilizar knockout.js en nuestra aplicación MVC3. Como ya tenemos jQuery selector de fechas y tenemos que formatear fechas de manera diferente según el entorno local (portal cuenta con diferentes idiomas y diferentes formatos son presentados por idioma), por lo que tal vez este mashup de los requerimientos tecnológicos surgen en otro lugar y será útil:

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

Y en la vista entonces, por ejemplo:

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

Una alternativa más limpia a la respuesta de @ photo_tom es decorar la propiedad con el IsoDateTimeConverter a través del atributo JsonConverter, así:

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

La mejor forma de manejar las fechas en knockoutjs es usar la biblioteca de momentos y manejar fechas como boss. Puede tratar fácilmente fechas como/Fecha (-62135578800000) /. No es necesario molestarse en cómo serializar la fecha en el controlador.

Enfoque 1: Directamente a la vista:

permite decir su modelo nocaut obtiene dicha fecha en un observables llamada sentDate y ahora tiene valor/Fecha (-62135578800000) /. Para obligar a éste a la vista que puede hacer:

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

Enfoque 2: En la costumbre de unión

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

    } 
}; 

Uso mismo que usted había dicho:

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

momentjs soporta un montón de fecha formatos de tiempo y funciones de utilidad en fechas.

+0

Tnx ajay, en este momento js me salvó el día, me gusta el método fácil de Approach 1 – DEBAL

0

Me encantó la respuesta de Andres Toro, excepto que en mi caso, los campos de entrada esperan cadenas formateadas. Así que estoy usando JQuery para formatear mis fechas de acuerdo con mi formato favorito proporcionado por mi ayudante @Html.ConvertDateFormat() Espero que esto ayude a alguien día.

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