【问题标题】:Single select options binding with jQuery validation is not working与 jQuery 验证绑定的单选选项不起作用
【发布时间】:2011-10-08 07:08:36
【问题描述】:

我正在使用敲除将对象列表绑定到select。对象类可以有任意数量的属性

<select id="TheProperty_City" 
        name="TheProperty_City" 
        class="required" 
        data-bind="options: cityList, 
                   optionsText: 'Name',  
                   value: selectedCity, 
                   optionsCaption: '--select the city--'" />

这很好用,我可以使用viewModel.selectedCity().NameviewModel.selectedCity().Value 来加载子元素。

我的问题是 jQuery 验证。如果我离开上面的语句,即使在选择之后,jQuery 也不会重置错误。

我通过在绑定中指定optionsValue 来修复它,但随后selectedCity 返回标量值而不是整个对象。知道如何保留对象行为或以不同方式进行验证吗?

 <select id="TheProperty_City" 
         name="TheProperty_City" 
         class="required" 
         data-bind="options: cityList, 
                    optionsText: 'Name',  
                    optionsValue: 'Value', //added the optionsValue
                    value: selectedCity, 
                    optionsCaption: '--select the city--'" />

当未指定optionsValue 时,错误仍然存​​在:

这是我在 selectedCity 上的 Object Watch:

当指定optionsValue 时,这是selectedCity 上的对象监视:

【问题讨论】:

    标签: jquery asp.net asp.net-mvc jquery-validate knockout.js


    【解决方案1】:

    问题在于,在将对象作为值处理时,option 元素的值设置为“”。因此,jQuery 验证失败。您可以编写一个绑定或包装绑定到 options 绑定,该绑定通过并将它们设置为一个值,但我认为最好不要走这条路。

    一个不错的选择是存储该值并使用dependentObservable 来表示当前选择的对象。

    应该是这样的:

    var viewModel = {
        cityList: [{ Name: "Madison", Value: "MSN" }, { Name: "Milwaukee", Value: "MKE" }, { Name: "Green Bay", Value: "GRB" }],
        selectedCityValue: ko.observable()
    };
    
    viewModel.selectedCity = ko.dependentObservable(function() {
        var value = this.selectedCityValue();
        return ko.utils.arrayFirst(this.cityList, function(city) {
           return city.Value === value; 
        });
    }, viewModel);
    

    使用如下绑定:

    <select id="TheProperty_City" name="TheProperty_City" class="required" 
        data-bind="options: cityList, 
        optionsText: 'Name', 
        optionsValue: 'Value',
        value: selectedCityValue, 
        optionsCaption: '--select the city--'" />
    

    示例:http://jsfiddle.net/rniemeyer/EgCM3/

    【讨论】:

    • 谢谢,这就是我所采用的解决方法,但对所有下拉菜单执行此操作很乏味。我的 knockoutjs 脚本正在快速增长,我想知道是否值得付出努力,因为您失去了 mvc Html 控件帮助程序、服务器 ViewModel 数据注释和内置验证支持。当然数据绑定很棒。无论如何,我会将其作为帮助其他搜索者的答案。
    • 您将如何实现自定义绑定来解决此问题?
    • 我遇到了同样的问题,并以与 RP Niemeyer 描述的相同方式解决。仍然想知道如何使它更好,因为正如 Jason 所写的那样,对于大型视图模型来说并非不可读。
    • 有没有人为此想出一个绑定解决方案,这个解决方案确实有效,但在中大型视图模型中变得非常难以管理。
    【解决方案2】:

    相当巧妙的解决方案是将 optionsAfrerRender 参数添加到选项绑定。假设在“selectedCity”对象中有一个字段“cityId”,您可以将其分配给选项值。请根据您的示例检查以下解决方案:

     <select id="TheProperty_City" 
        name="TheProperty_City" 
        class="required" 
        data-bind="options: cityList, 
                   optionsText: 'Name',
                   value: selectedCity,
                   optionsAfterRender: function(option, item) 
                                            { option.value = item.cityId; }
                   optionsCaption: '--select the city--'" />
    

    使用这种方法,您将同时使用淘汰赛选项绑定和 jquery 验证。

    【讨论】:

    • 在与 Bootstrap 验证器集成时,这可以很好地解决怪异问题。
    【解决方案3】:

    上述答案有一个警告。第一个选择值绑定(“--select the city--”)将未定义,导致错误。

    如果你修改代码来处理这个问题。

    <select id="TheProperty_City" 
    name="TheProperty_City" 
    class="required" 
    data-bind="options: cityList, 
               optionsText: 'Name',
               value: selectedCity,
               optionsAfterRender: setOptionValue
               optionsCaption: '--select the city--'" />
    

    注意:为了简洁起见,我已经从 ViewModel 中删除了所有内容,除了 setOptionValue 方法。

    <script type="text/javascript">
    var vm = {
        setOptionValue: function(option, item) {
            if (item === undefined) {
                option.value = "";
            } else {
                option.value = item.id;
            }
        }
    };
    ko.applyBindings(vm);
    

    【讨论】:

    • 更进一步:在setOptionValue func 中,将属性名称作为第三个参数(propId)传递,然后执行option.value = item[propId]。这现在可以用于具有不同模型绑定的任何下拉菜单。
    【解决方案4】:

    为了扩展 Robert 的回答,我们可以通过允许用户传入正确属性的字符串,使辅助函数适用于视图模型中的每个下拉菜单,无论上下文数据绑定如何:

    JS

    self.setOptionValue = function(propId) {
        return function (option, item) {
            if (item === undefined) {
                option.value = "";
            } else {
                option.value = item[propId];
            }
        }
    };
    

    HTML

    <select class="custom-dropdown" data-bind="options: cityList, 
            optionsAfterRender: setOptionValue('AppointmentTypeId'), value: selectedCityObj, optionsCaption: 'Choose...'" data-validation="required"></select>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-12
      • 2017-07-21
      • 2021-01-31
      • 2018-04-01
      • 2012-12-25
      • 2016-12-01
      • 1970-01-01
      • 2015-01-16
      相关资源
      最近更新 更多