2012-06-20 15 views
21

Esta pregunta es similar a knockoutjs databind with jquery-ui datepicker, pero en lugar del jQueryUI datepicker, me gustaría utilizar uno de los Bootstrap datepickers.Marcador de fecha Bootstrap con databind knockout.js

La API para el marcador de fechas de Bootstrap es diferente de jquery-ui, y estoy teniendo problemas para hacer que funcione con knockout.js. He creado a jsFiddle to try it out.

Parece que el datepicker Bootstrap podría ser mucho más simple de usar porque no almacena la fecha de forma independiente. Sin embargo, me gustaría saber cómo si el jsFiddle es la forma adecuada de utilizar el widget selector de fechas Bootstrap con knockout.js es decir

ko.bindingHandlers.datepicker = { 
    init: function(element, valueAccessor, allBindingsAccessor) { 
     //initialize datepicker with some optional options 
     var options = allBindingsAccessor().datepickerOptions || {}; 
     $(element).datepicker(options); 

     ko.utils.domNodeDisposal.addDisposeCallback(element, function() { 
      $(element).datepicker("destroy"); 
     }); 
    }, 
    update: function(element, valueAccessor) { 
    } 
}; 

Respuesta

40

Este es un ejemplo de cómo se puede lograr esto con el selector de fecha que está utilizando :

ko.bindingHandlers.datepicker = { 
    init: function(element, valueAccessor, allBindingsAccessor) { 
     //initialize datepicker with some optional options 
     var options = allBindingsAccessor().datepickerOptions || {}; 
     $(element).datepicker(options); 

     //when a user changes the date, update the view model 
     ko.utils.registerEventHandler(element, "changeDate", function(event) { 
      var value = valueAccessor(); 
      if (ko.isObservable(value)) { 
       value(event.date); 
      }     
     }); 
    }, 
    update: function(element, valueAccessor) { 
     var widget = $(element).data("datepicker"); 
     //when the view model is updated, update the widget 
     if (widget) { 
      widget.date = ko.utils.unwrapObservable(valueAccessor()); 
      if (widget.date) { 
       widget.setValue();    
      } 
     } 
    } 
}; 

no se veía como había alguna destruir la funcionalidad, por lo que elimina esa pieza. Esto maneja el evento widgets changeDate para actualizar el modelo de vista, cuando un usuario cambia la fecha. La función update se ocupa cuando se cambia el modelo de vista para actualizar el widget.

Si desea vincular el valor a un no observable, se necesitaría un poco más de código. Avísame si eso es algo que necesitas apoyar.

http://jsfiddle.net/rniemeyer/KLpq7/

+2

Aquí está a [jsFiddle] (http://jsfiddle.net/bmh_ca/uQcCx/2/) que tiene una conversión de cadena-> fecha más fácil cuando se actualiza el campo. Esto todavía tiene la advertencia de que solo se registran los cambios a través del widget; hacer cambios en el campo de entrada no actualiza el modelo. –

+2

Aquí hay una actualización para vincularse con el evento 'change' para responder a los cambios en el campo de entrada: http://jsfiddle.net/rniemeyer/uQcCx/3/ –

+0

JsFiddles arriba parece que ya no funciona, ¿has hecho algunos cambios desde?, probado Chrome y Firefox, datepicker ya no aparece. Cheers – dtjmsy

2

Esto es lo que terminó

ko.bindingHandlers.datepicker = { 
init: function (element, valueAccessor, allBindingsAccessor) { 
    //initialize datepicker with some optional options 

    var options = { 
     autoclose: true, 
     format: 'yyyy-mm-dd', 
    } 

    //var options = allBindingsAccessor().datepickerOptions || {}; 
    $(element).datepicker(options); 

    //when a user changes the date, update the view model 
    ko.utils.registerEventHandler(element, "changeDate", function (event) { 
     var value = valueAccessor(); 

     if (ko.isObservable(value)) { 
      var myDate = event.date; 
      var month = myDate.getMonth() + 1; 
      var monthText = month; 

      if (month < 10) 
       monthText = "0" + month; 

      var day1 = parseInt(myDate.getDate()); 
      var dayText = day1; 

      if (day1 < 10) 
       dayText = '0' + day1; 

      value(myDate.getFullYear() + '-' + monthText + '-' + dayText); 
     } 
    }); 
}, 
update: function (element, valueAccessor) { 

    var widget = $(element).data("datepicker"); 
    //when the view model is updated, update the widget 
    if (widget) { 
     widget.date = ko.utils.unwrapObservable(valueAccessor()); 
     widget.setValue(widget.date); 
    } 
}}; 
5

La respuesta aceptada que no funcionó para mí con la versión actual del selector de fecha. La entrada no se estaba inicializando con el valor de lo observable. Hice un enlace actualizado, al cual agregué esto:

$(element).datepicker('update', dataSource()); 

Eso parece hacer el truco.

He aquí un violín actualizado que utiliza la última selector de fechas disponibles, Bootstrap, jQuery, y Knockout: http://jsfiddle.net/krainey/nxhqerxg/

Actualización:

he experimentado algunas dificultades con el selector de fechas no jugar bien con lo observable cuando un usuario edita el valor en el campo de texto manualmente. La herramienta analizará inmediatamente la fecha y conectará el resultado en el campo de entrada.

Si el usuario intentó editar 10/07/2014, por ejemplo, y utilizó el retroceso o eliminar para eliminar un número (10/0/2014), el valor resultante se analizará inmediatamente y se insertará en el ingreso de texto . Si el valor fue, por un momento, 10/0/2014, el selector cambiaría el calendario a 30/09/2014 y conectaría ese valor al campo de texto. Si traté de editar el mes, y el valor fue, por un momento, 1/7/2014, el selector cambiaría al 7 de enero de 2014 y conectaría ese valor en el campo de texto.

Se puede ver que el comportamiento en este violín:

http://jsfiddle.net/krainey/nxhqerxg/10/

que tenía que actualizar mi unión con un controlador especial para detectar el foco, y enlazar un evento de falta de definición de una sola vez para conseguir que le permite manejar Manual edita correctamente

$(element).on("changeDate", function (ev) { 
    var observable = valueAccessor(); 
    if ($(element).is(':focus')) { 
     // Don't update while the user is in the field... 
     // Instead, handle focus loss 
     $(element).one('blur', function(ev){ 
      var dateVal = $(element).datepicker("getDate"); 
      observable(dateVal); 
     }); 
    } 
    else { 
     observable(ev.date); 
    } 
}); 

El violín se hace referencia en la respuesta original ha sido actualizado para reflejar esto:

http://jsfiddle.net/krainey/nxhqerxg/

5

mi versión actual es una mezcla entre las soluciones ya que se muestran:

ko.bindingHandlers.datepicker = { 
init: function (element, valueAccessor, allBindingsAccessor) { 

    var unwrap = ko.utils.unwrapObservable; 
    var dataSource = valueAccessor(); 
    var binding = allBindingsAccessor(); 

    //initialize datepicker with some optional options 
    var options = allBindingsAccessor().datepickerOptions || {}; 
    $(element).datepicker(options); 
    $(element).datepicker('update', dataSource()); 
    //when a user changes the date, update the view model 
    ko.utils.registerEventHandler(element, "changeDate", function (event) { 
     var value = valueAccessor(); 
     if (ko.isObservable(value)) { 
      value(event.date); 
     } 
    }); 
}, 
update: function (element, valueAccessor) { 
    var widget = $(element).data("datepicker"); 

    var value = ko.utils.unwrapObservable(valueAccessor()); 

    //when the view model is updated, update the widget 
    if (widget) { 
     widget.date = value; 
     if (widget.date) { 
      widget.setValue(); 
      $(element).datepicker('update', value) 
     } 
    } 
}}; 
Cuestiones relacionadas