简体   繁体   English

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

[英]MVC 4 - Knockout custom binding and date format

I am using Asp.Net MVC 4 and Knockout in a form. 我在表单中使用Asp.Net MVC 4和Knockout。

I have a date input that i wish to format. 我有一个我希望格式化的日期输入。

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

My problem is when i submit the form, i don't have the date filled in the posted JSON. 我的问题是,当我提交表单时,我没有在发布的JSON中填写日期。

I think the problem is located in the custom handler, but i can't find out :( The update event fires only once at load. 我认为问题位于自定义处理程序中,但我无法找到:(更新事件仅在加载时触发一次。

View Code 查看代码

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

Custom binding Code 自定义绑定代码

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 ko绑定代码

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

Note : the date format is working as expecting. 注意:日期格式正如预期的那样工作。

What am i doing wrong ? 我究竟做错了什么 ? :( :(

Without seeing your ViewModel, I can only speculate. 没有看到你的ViewModel,我只能推测。 In your code, you are binding EndDate directly to your TextBox: 在您的代码中,您将EndDate直接绑定到TextBox:

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

Your EndDate observable doesn't know anything about this value. 您的EndDate observable对此值一无所知。 Therefore, if your EndDate observable looks something like this in your ViewModel: 因此,如果您的EndDate observable在ViewModel中看起来像这样:

this.EndDate = ko.observable();

Then it is unaware of the value that was bound directly to the TextBox by your ASP.NET MVC code. 然后它不知道ASP.NET MVC代码直接绑定到TextBox的值。 Therefore, when you apply your KO bindings, the EndDate value that was bound directly to the TextBox gets destroyed. 因此,当您应用KO绑定时,直接绑定到TextBox的EndDate值将被销毁。 If this is the case, you can either: (1) initialize the EndDate observable directly from the value bound from the server Model, or, (2) initialize the EndDate observable indirectly by using a custom KO binding that initializes the EndDate observable from the value that was bound directly to the TextBox. 如果是这种情况,您可以:(1)直接从服务器模型绑定的值初始化EndDate observable,或者(2)使用自定义KO绑定间接初始化EndDate observable,该绑定初始化EndDate observable直接绑定到TextBox的值。

Example 1 例1

This example assumes the JavaScript is directly in your view. 此示例假定JavaScript直接位于您的视图中。 If your JavaScript is in a separate file (as is typically the case), then you would have to pass the Model data into your ViewModel using another technique such as JSON serialization on the client before binding your ViewModel. 如果您的JavaScript位于单独的文件中(通常就是这种情况),则必须在绑定ViewModel之前使用客户端上的JSON序列化等其他技术将Model数据传递到ViewModel。

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

Example 2 例2

The sequential order of the KO binding parameters is important in this example. 在该示例中,KO绑定参数的顺序是重要的。 The new custom binding must be the first binding in order for this to work properly: 新的自定义绑定必须是第一个绑定才能使其正常工作:

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

And here is the code for the custom KO binding: 这是自定义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);
    }
};

At last, i found the solution ! 最后,我找到了解决方案!

The custom binding should look like that : 自定义绑定应如下所示:

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

It uses the default value binding plus my custom date format. 它使用默认值绑定加上我的自定义日期格式。 Only on init because the update is managed by a datepicker which is correctly formated. 仅在init上,因为更新由正确格式化的datepicker管理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM