敲除双向自定义绑定以在日期和时间字段中拆分ISO日期时间

时间:2018-02-09 21:59:18

标签: knockout.js

我在服务器端有一个datetimestring YYYY-MM-DDT03:00,在客户端有一个moment.js。

我需要将绑定处理程序的更新和初始化阶段绑定到我的可观察日期时间属性,但无法使其与表单输入一起使用。

这是文本元素的工作理念(仅更新阶段):

ko.bindingHandlers.date = {
    update: function(element, valueAccessor) {
        var options = ko.unwrap(valueAccessor);
        var value = ko.unwrap(options.value);
        var text = moment(value).format('DD/MM/YYYY');
        ko.utils.setTextContent(element, text);
    },
};
ko.bindingHandlers.time = {
    update: function(element, valueAccessor) {
        var options = ko.unwrap(valueAccessor);
        var value = ko.unwrap(options.value);
        var text = moment(value).format('HH:mm');
        ko.utils.setTextContent(element, text);
    },
};

编辑 - 我尝试对我的问题进行语境化。

实际上,作为淘汰赛和js新手:),我试图从服务器(每个项目可以有各种属性)映射以太网Json数组,以通过ko.mapping淘汰observables。最终我需要一个ko可观察数组,其中包含每个原始数组项的编辑/保存/取消/删除方法。

function EditableCollection(payload, updateUrl) {
    /* EditableCollections = { item: actual object,
     *                         data: actual data,
     *                         edit, editing Knockout facility,
     *                       }
     */
    var collection = this;
    collection.item = ko.mapping.fromJS(payload);

    collection.editing = ko.observable(false);

    collection.edit = function() {
        if (!self.condition()) {
            // UI logic
            collection._bkp = ko.mapping.toJS(collection.item);
            collection.editing(true);
        } else {
            // UI logic
        };
    };
    collection.cancel = function() {
        ko.mapping.fromJS(collection._bkp, collection.item);
        delete(collection._bkp);
        collection.editing(false);
        // UI logic
    };
    collection.item.cancel = collection.cancel;
    collection.save = function() {
        if (updateUrl) {
        $.ajax({
            url: updateUrl,
            method:'POST',
            dataType:'json',
            data: JSON.stringify($.extend(updateData, { 'item': ko.mapping.toJS(collection.item) })), // or something
            success: function(result){
            return result;
            },
            error: function(error){
            return error;
            },
        });
        };
        // UI logic
        delete(collection._bkp);
    };
    collection.item.save = collection.save;
};

原始问题的出现是因为当我面对包含ISO 8601字符串的项目的数组时,我需要在两个单独的属性日期和时间进行转换。

所以我认为我不能使用calculateProperties。作为原始绑定方法的一种解决方法,我试图在映射create function中管理任务,但对我来说这是非常低效和丑陋的:

var scadenzeMapping = {
create: function(options) {
    var payload = options.data;
    console.log(payload);
    // ** moment.js:
    // When refactoring for TIME will matter.
    var start = moment(payload.data_start); // e.g. 05/02/2018T00:00:00
    // TODO ** Verify timezone (external) handling...
    if (payload.isAllDay) {
        payload.sdate = start.format('DD/MM/YYYY');
        payload.stime = undefined;
        payload.edate = payload.sdate;
        payload.etime = undefined;
        payload.data_end = payload.data_start;
    } else {
        payload.sdate = start.format('DD/MM/YYYY');
        payload.stime = start.format('HH:mm');
        var end = moment(payload.data_end);
        payload.edate = end.format('DD/MM/YYYY');
        payload.etime = end.format('HH:mm');
    };
    // payload.data_start = start;
    return new EditableCollection(payload,
                                  '{{ put_event }}',
                                  );
    },
};

这是原始问题的主题背景。

1 个答案:

答案 0 :(得分:0)

首先,您的自定义绑定不会订阅传递的observable的更改。如果你改变了

var options = ko.unwrap(valueAccessor);

var options = ko.unwrap(valueAccessor());

在传递的observable发生更改后调用您的更新函数。

其次,如果您尝试在输入上使用此绑定,则无法使用

ko.utils.setTextContent(element, text);

因为它改变了元素的内容,而不是值。你需要使用

element.value = text;

我认为做这种事情的最好方法是没有自定义绑定,使用可写计算机,并使用标准值绑定,如下所示:

var myObservable = ko.observable();
var myComputed = ko.computed({
    write: function(val){
        myObservable(moment(val, 'DD/MM/YYYY').format('YYYY-MM-DDTHH:mm'))
    },
    read: function(){
        return moment(myObservable()).format('DD/MM/YYYY');
    }
})

在html中:

<input data-bind="value: myComputed"/>