【问题标题】:Bootstrap datepicker with knockout.js databindBootstrap datepicker with knockout.js 数据绑定
【发布时间】:2012-06-22 17:33:24
【问题描述】:

这个问题类似于knockoutjs databind with jquery-ui datepicker,但我想使用Bootstrap datepickers之一而不是jQueryUI datepicker。

Bootstrap datepicker 的 API 与 jquery-ui 不同,我在想办法让它与 knockout.js 一起工作时遇到了一些麻烦。我创建了a jsFiddle to try it out

Bootstrap 日期选择器似乎更易于使用,因为它不独立存储日期。但是,我想知道 jsFiddle 是否是使用带有 knockout.js 的 Bootstrap datepicker 小部件的适当方式,即

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

【问题讨论】:

    标签: datepicker knockout.js twitter-bootstrap


    【解决方案1】:

    这是一个示例,说明如何使用您正在使用的日期选择器完成此操作:

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

    看起来没有任何破坏功能,所以我删除了那块。当用户更改日期时,这将处理小部件changeDate 事件以更新视图模型。 update 函数处理视图模型更改以更新小部件。

    如果你想将值绑定到不可观察的值,那么需要更多的代码。如果您需要支持,请告诉我。

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

    【讨论】:

    • 这是一个jsFiddle,在字段更新时具有更适合的字符串->日期转换。这仍然需要注意,只有通过小部件进行的更改才会被注册;对输入字段进行更改不会更新模型。
    • 以下是绑定change 事件以响应输入字段更改的更新:jsfiddle.net/rniemeyer/uQcCx/3
    • 上面的 JsFiddles 似乎不再工作了,您是否进行了一些更改?,测试了 chrome 和 firefox,datepicker 不再显示。干杯
    • 我弄明白了,外部调试knockoutjs的链接已经失效了
    • 我注意到这个例子不再有效,因为日期选择器的初始日期不是文本框中的日期。这是我试图在自己的代码中修复的错误。有什么想法吗?
    【解决方案2】:

    我当前的版本是已经显示的解决方案的混合:

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

    【讨论】:

      【解决方案3】:

      接受的答案不适用于当前版本的日期选择器。输入没有用可观察的值初始化。我做了一个更新的绑定,我添加了这个:

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

      这似乎可以解决问题。

      这是一个使用最新可用日期选择器、Bootstrap、jQuery 和 Knockout 的更新小提琴:http://jsfiddle.net/krainey/nxhqerxg/

      更新:

      当用户手动编辑文本字段中的值时,我遇到了一些困难,日期选择器不能很好地与 observable 配合使用。该工具将立即解析日期,并将结果插入输入字段。

      例如,如果用户尝试编辑 10/07/2014,并使用退格键或 delete 删除数字 (10/0/2014),则结果值将立即解析并插入到文本输入中。如果该值暂时是 2014 年 10 月 0 日,则选择器会将日历移动到 2014 年 9 月 30 日,并将该值插入文本字段。如果我尝试编辑月份,并且该值暂时为 2014 年 1 月 7 日,那么选择器将切换到 2014 年 1 月 7 日,并将该值插入到文本字段中。

      你可以在这个小提琴中看到这种行为:

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

      我必须使用特殊处理程序更新我的绑定以检测焦点,并绑定一次性模糊事件以使其正确处理手动编辑。

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

      原始答案中引用的小提琴已更新以反映这一点:

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

      【讨论】:

        【解决方案4】:

        这就是我的结局

        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】:

          有一种更简单的方法可以让 bootstrap-datepicker.js 和 knockout.js 一起工作。通常在页面加载期间/之后调用datepicker 输入的初始化。但是,当 knockout.js 更新值绑定时,datepicker 没有正确更新为新值,因此当您关注 datepicker 输入时,它默认为 2001 年 1 月 1 日。

          您所要做的就是在根据下面的 ViewModel 方法更新任何 knockout.js 值绑定后销毁并重新初始化 datepicker 输入,该方法设置要编辑的映射对象。

          self.showEditOrderForm = function (data) {
              ko.mapping.fromJS(data, self.entity);
              self.mode('edit');
              $('#edit-dateordered').datepicker('destroy');
              $('#edit-dateordered').datepicker({
                  format: 'dd-M-yyyy',
                  title: 'Select Date',
                  weekStart: 1,
                  todayHighlight: true,
                  autoClose: true,
                  endDate: '0d'
              });
          };
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-11-22
            • 1970-01-01
            • 1970-01-01
            • 2021-08-03
            • 2023-03-15
            • 2017-12-06
            • 2018-02-12
            相关资源
            最近更新 更多