Knockout JS “uniqueName” binding - Same name to tw

2020-03-25 05:49发布

I am using Knockout JS to create an editor. I am using the foreach property to loop around a list in my model.

 <tbody data-bind='foreach: Properties'>

I am using JQuery unobtrusive validation whichneeds a name property to validate. I want to assign the same name to two fields, in order to be able to output a validation message. Is it possible to use the same uniqueName property on two fields?

 <tr>
     <td>
         <input data-bind='value: type, uniqueName: true' data-val = "true", data-val-required = "The Type field is required"  /></td>
     </td>
 </tr>
 <tr>
     <td class="field-validation-valid" data-valmsg-for="UNIQUENAME" data-valmsg-replace="true"></td>
 </tr>

Ive copied the example below which shows grid editing and JQuery unobtrusive validation. But i cant work out how to link the validation message with the input field

http://knockoutjs.com/examples/gridEditor.html

Edit:

I am using ASP.NET MVC3 with Razor syntax for the loop input.

 @Html.DropDownList("Type", new SelectList(types, "Value", "Text"), "Select", new { data_bind = "value: Type", data_val = "true", data_val_required = "The Type field is required" })

I cant figure out how to update the name property. When i add a property using knokcout they all have the same name "Type" and the validation doesn't work. They need to be indexed some how Type1 Type2 etc.

标签: knockout.js
4条回答
我命由我不由天
2楼-- · 2020-03-25 06:32

A possibly simpler approach derived from RP-Niemeyer's excellent solution:

<span class="field-validation-valid" data-bind='attr: {"data-valmsg-for": "ko_unique_" + ko.bindingHandlers.uniqueName.currentIndex}' data-valmsg-replace="true" />
查看更多
够拽才男人
3楼-- · 2020-03-25 06:33

The uniqueName binding just increments an index and sets the name (with a fix for IE).

It looks like:

ko.bindingHandlers['uniqueName'] = {
    'init': function (element, valueAccessor) {
        if (valueAccessor()) {
            element.name = "ko_unique_" + (++ko.bindingHandlers['uniqueName'].currentIndex);

            // Workaround IE 6/7 issue
            // - https://github.com/SteveSanderson/knockout/issues/197
            // - http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
            if (ko.utils.isIe6 || ko.utils.isIe7)
                element.mergeAttributes(document.createElement("<input name='" + element.name + "'/>"), false);
        }
    }
};

So, you can create a custom binding that uses the last index and sets the appropriate attribute

ko.bindingHandlers.valmsg = {
    init: function(element) {
        element.setAttribute("data-valmsg-for", "ko_unique_" + ko.bindingHandlers.uniqueName.currentIndex);
    }
};

Now, you would just use it like:

<tr>
    <td>
         <input data-bind='value: type, uniqueName: true' data-val="true", data-val-required="The Type field is required"  />
    </td>
</tr>
<tr>
     <td class="field-validation-valid" data-bind="valmsg: true" data-valmsg-replace="true"></td>
</tr>
查看更多
一纸荒年 Trace。
4楼-- · 2020-03-25 06:33

I wanted to post as a comment, but my reputation is too low... Thank you very much RP Niemeyer for your post.

I don't know if this has something to do with requirejs and knockout modules, but I had to change

ko.bindingHandlers.uniqueName.currentIndex 

to

ko.bindingHandlers.uniqueName.Zb

so now I have:

define(["knockout"], function(ko) {
    ko.bindingHandlers.valmsg = {
        init: function (element) {
            element.setAttribute("data-valmsg-for", "ko_unique_" + ko.bindingHandlers.uniqueName.Zb);
        }
    };
});
查看更多
beautiful°
5楼-- · 2020-03-25 06:36

You only need to add a ControlName attribute in the child elements and bind the input name to this and the data-valms-for too

<input type="number" class="form-control" data-bind="value: myValue, valueUpdate: 'afterkeydown', attr: {ControlName}" required /> 
<span class="field-validation-valid" data-bind='attr: {"data-valmsg-for":ControlName}' data-valmsg-replace="true"></span>
查看更多
登录 后发表回答