MVC 4 - Knockout自定义绑定和日期格式

时间:2014-06-29 19:12:22

标签: asp.net-mvc date knockout.js format

我在表单中使用Asp.Net MVC 4和Knockout。

我有一个我希望格式化的日期输入。

我最终得到了这个解决方案: http://jason-mitchell.com/web-development/binding-dates-using-knockout-moment-js/

我的问题是,当我提交表单时,我没有在发布的JSON中填写日期。

我认为问题出在自定义处理程序中,但我无法找到:( 更新事件仅在加载时触发一次。

查看代码

@Html.TextBoxFor(Function(model) model.EndDate, New With {.data_bind = "date: EndDate"})

自定义绑定代码

ko.bindingHandlers.date = {   
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var value = valueAccessor();
        var valueUnwrapped = ko.utils.unwrapObservable(value);
        var allBindings = allBindingsAccessor();

        // Date formats: http://momentjs.com/docs/#/displaying/format/
        var pattern = allBindings.format || 'L';

        var output = "";
        if (valueUnwrapped !== null && valueUnwrapped !== undefined && valueUnwrapped.length > 0) {
            output = moment(valueUnwrapped).format(pattern);
        }

        if ($(element).is("input") === true) {
            $(element).val(output);
        } else {
            $(element).text(output);
        }
    }
};

ko binding Code

var viewModel = ko.mapping.fromJS(@Html.Raw(Model.ToJson()));
ko.applyBindings(viewModel);

注意:日期格式正如期望的那样。

我做错了什么? :(

2 个答案:

答案 0 :(得分:2)

没有看到你的ViewModel,我只能推测。在您的代码中,您将EndDate直接绑定到TextBox:

@Html.TextBoxFor(Function(model) model.EndDate, New With {.data_bind = "date: EndDate"})

您的EndDate observable对此值一无所知。因此,如果您的EndDate observable在ViewModel中看起来像这样:

this.EndDate = ko.observable();

然后它不知道ASP.NET MVC代码直接绑定到TextBox的值。因此,当您应用KO绑定时,直接绑定到TextBox的EndDate值将被销毁。如果是这种情况,您可以:(1)直接从服务器Model绑定的值初始化EndDate observable,或者(2)使用自定义KO绑定间接初始化EndDate observable,该绑定初始化EndDate observable直接绑定到TextBox的值。

示例1

此示例假定JavaScript直接位于您的视图中。如果您的JavaScript位于单独的文件中(通常就是这种情况),那么在绑定ViewModel之前,您必须使用客户端上的JSON序列化等其他技术将Model数据传递到ViewModel。

this.EndDate = ko.observable('@Model.EndDate.ToString()');

示例2

在此示例中,KO绑定参数的顺序很重要。新的自定义绑定必须是第一个绑定才能使其正常工作:

@Html.TextBoxFor(Function(model) model.EndDate, New With {.data_bind = "initInputFromView: EndDate, date: EndDate"})

以下是自定义KO绑定的代码:

ko.bindingHandlers.initInputFromView = {
    init: function (element, valueAccessor) {
        // reads the value stored in the <input> value attribute and initializes the observable with that value
        valueAccessor()(element.value);
    }
};

答案 1 :(得分:1)

最后,我找到了解决方案!

自定义绑定应如下所示:

ko.bindingHandlers.date = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {       
        ko.bindingHandlers.value.init(element, valueAccessor, 
             allBindingsAccessor, viewModel, bindingContext);

        var value = valueAccessor();
        var valueUnwrapped = ko.utils.unwrapObservable(value);
        var allBindings = allBindingsAccessor();
        // Date formats: http://momentjs.com/docs/#/displaying/format/
        var pattern = allBindings.format || 'L';

        var output = valueUnwrapped;
        if (valueUnwrapped !== null && valueUnwrapped !== undefined && valueUnwrapped.length > 0) {
            output = moment(valueUnwrapped).format(pattern);
        }

        if ($(element).is("input") === true) {
            $(element).val(output);
        } else {
            $(element).text(output);
        }           
    },   
};

它使用默认值绑定加上我的自定义日期格式。 仅在init上,因为更新由正确格式化的datepicker管理。