Knockout observableArray 没有被继承的 datepicker 值填充

Posted

技术标签:

【中文标题】Knockout observableArray 没有被继承的 datepicker 值填充【英文标题】:Knockout observableArray not being populated by inherited datepicker value 【发布时间】:2017-07-27 13:56:47 【问题描述】:

我在使用从日期选择器继承的值填充 observableArray 时遇到问题。我有一个禁用的文本框,它显示日期选择器的值作为数据收集部分的一部分。由于它被禁用并且没有被输入,它不会更新 observableArray。

我创建了一个example jsfiddle,我已经在其中剥离并定位了问题。

任何让值出现在 observableArray 中的帮助都会很棒,因为我真的很难弄清楚这一点!

HTML

<!--Date Load -->
<span><b>Select a date:</b></span>
<span><input id="theDate" data-bind="datepicker: viewModelWardStaff.dateMonthYear, datepickerOptions:  dateFormat: 'dd/mm/yy'  "></span>

<!--Input Form -->
<span><h4>Input New Entries</h4></span>
<div style="border: solid 1px;" data-bind="with: viewModelWardStaff">
    <form class="grid-form" id="dataCollection">
        <fieldset>
            <div data-row-span="1">
                <div data-field-span="1">
                    <label>Date</label>
                    <input id="cDate" class="autosend" data-bind="textInput: dateMonthYear, enable: false">
                </div>
                <div data-field-span="1">
                    <label>Status</label>
                    <input id="cStatus" maxlength="200" class="autosend" data-bind="textInput: wardstaff.Status" type="text">
                </div>
            </div>
        </fieldset>
        <div style="margin: 5px;">
            <a style="margin-left: 300px;" id="addFileButton" class="button-link" data-bind="click: viewModelWardStaff.addEntry">Add</a>
        </div>
    </form>
</div>
<h4>View Model Ward Staff</h4>
    <div data-bind="with: viewModelWardStaff">
    <pre data-bind="text: ko.toJSON($data, null, 2)"></pre>
</div>

KnockoutJS

moment.locale('en-gb');

function WardStaff(data) 
    var self = this;
    self.Date = ko.observable(data.Date());
    self.Status = ko.observable(data.Status());
;

function oWardStaff() 
    var self = this;
    self.Date = ko.observable();
    self.Status = ko.observable();
;

var viewModelWardStaff = function () 

    var self = this;

    self.wardstaff = new oWardStaff();

    self.dateMonthYear = ko.observable();

    self.entries = ko.observableArray([]);

    self.addEntry = function () 
        self.entries.push(new WardStaff(self.wardstaff));
    

    self.removeEntry = function (entry) 
        self.entries.remove(entry);
    
;

// dateString knockout
ko.bindingHandlers.dateString = 
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) 
        var value = valueAccessor(),
            allBindings = allBindingsAccessor();
        var valueUnwrapped = ko.utils.unwrapObservable(value);
        var pattern = allBindings.datePattern || 'YYYY-MM-DD HH:mm:ss';
        if (valueUnwrapped == undefined || valueUnwrapped == null) 
            $(element).text("");
        
        else 
            var date = moment(valueUnwrapped, "YYYY-MM-DDTHH:mm:ss"); //new Date(Date.fromISO(valueUnwrapped));
            $(element).text(moment(date).format(pattern));
        
    


//datepicker knockout
ko.bindingHandlers.datepicker = 
    init: function (element, valueAccessor, allBindingsAccessor) 
        //initialize datepicker with some optional options
        var options = allBindingsAccessor().datepickerOptions || ;
        $(element).datepicker(options);
        //WORK
        //handle the field changing
        ko.utils.registerEventHandler(element, "change", function () 
            var observable = valueAccessor();

            if (moment($(element).datepicker("getDate")).local().format('YYYY-MM-DD') == 'Invalid date') 
                observable(null);
            
            else 
                observable(moment($(element).datepicker("getDate")).local().format('YYYY-MM-DD'));
            

        );

        //handle disposal (if KO removes by the template binding)
        ko.utils.domNodeDisposal.addDisposeCallback(element, function () 
            $(element).datepicker("destroy");
        );

    ,
    //update the control when the view model changes
    update: function (element, valueAccessor) 
        var value = ko.utils.unwrapObservable(valueAccessor());
        current = $(element).datepicker("getDate");

        if (moment(value).format('DD/MM/YYYY') == 'Invalid date') 
            $(element).datepicker("setDate", null);
        

    
;

// Master View Model
var masterVM = function () 
    var self = this;

    self.viewModelWardStaff = new viewModelWardStaff();

;

// Activate Knockout
ko.applyBindings(masterVM);

【问题讨论】:

对knockout.js的了解不够,无法帮助您,无论如何使用moment isValid(在您的情况下为moment(value).isValid())来检查moment对象是否有效,而不是moment(value).format('DD/MM/YYYY') == 'Invalid date' 谢谢。 【参考方案1】:

我认为问题在于您的可观察日期dateMonthYear 存在于您的主视图模型中。 self.wardstaffDate 属性永远不会被设置。

您可以通过将主视图模型中的 observable 与 wardstaff 属性中的 observable 共享来解决此问题:

function oWardStaff(obsDate) 
    var self = this;
    self.Date = obsDate;
    self.Status = ko.observable();
;

/* ... */

self.dateMonthYear = ko.observable();
self.wardstaff = new oWardStaff(self.dateMonthYear);

现在,每当您选择一个新日期时,它都会将其写入两个视图模型引用的 observable。

这行突然变得有用了:

function WardStaff(data) 
    var self = this;
    self.Date = ko.observable(data.Date());      // <-- here
    self.Status = ko.observable(data.Status());
;

因为Date 现在已实际设置。

我认为现在可以正常工作的小提琴:https://jsfiddle.net/n0t91sra/ (如果我错过了其他一些想要的行为,请告诉我)

【讨论】:

非常感谢,当你知道的时候就很明显了!按预期工作!

以上是关于Knockout observableArray 没有被继承的 datepicker 值填充的主要内容,如果未能解决你的问题,请参考以下文章

从 .ajax() 调用加载一个 knockout.js observableArray()

双向数据绑定不适用于knockout ObservableArrays

Knockout-Kendo dropdownlist Ajax observableArray 获取选中项名称

KNOCKOUT JS observableArray重复

Knockout observableArray 没有被继承的 datepicker 值填充

如何使用 Knockout-Validation 将无效项目添加到 observableArray 以使 validObservable 无效