<select
data-bind="options: Actors, optionsText: 'Name',
value: Actor, optionsCaption: 'Choose an actor ...'" ></select>
Actors are a key/value pair with an ID and a name. So the default populates with the following two values.
"Actors": [
{
"Id": "actors/1",
"Name": "Character 1",
"Tags": null
},
{
"Id": "actors/2625",
"Name": "Character 2625",
"Tags": null
}
]
So then, the expected behavior is simple. It creates a dropdown list with a default value ("Choose an actor ...") and then you click the dropdown and pick one. So, after picking a value, the view model JSON looks exactly like this.
{
"Actor": {
"Id": "actors/1",
"Name": "Character 1",
"Tags": null
},
"Actors": [
{
"Id": "actors/1",
"Name": "Character 1",
"Tags": null
},
{
"Id": "actors/2625",
"Name": "Character 2625",
"Tags": null
}
]
}
Simple enough - it has worked fine for me up until now.
So I had a lot of people that were submitting the form without making a selection. So I attempted to plumb in and add some jQuery Validation and Unobtrusive Validation. I do this with the following code... (This part is fairly useless for the Knockout part, I am just showing you the code in case it might be of some use)
(function ($) {
$.validator.unobtrusive.adapters.addBool("mustbetrue", "required");
})(jQuery);
(function ($) {
// http://www.falconwebtech.com/post/2012/04/21/MVC3-Custom-Client-Side-Validation-with-Unobtrusive-Ajax.aspx
$.validator.addMethod('mustbe', function (value, element, params) {
var testValue = params['propertyvalue'];
var condition = params['condition'];
if ((condition == '0') && (value != testValue))
return true;
if ((condition == '1') && (value == testValue))
return true;
return false;
});
var setValidationValues = function (options, ruleName, value) {
options.rules[ruleName] = value;
if (options.message) {
options.messages[ruleName] = options.message;
}
};
$.validator.unobtrusive.adapters.add("mustbe", ["propertyvalue", "condition"], function (options) {
var value = {
propertyvalue: options.params.propertyvalue,
condition: options.params.condition
};
setValidationValues(options, "mustbe", value);
});
})(jQuery);
Okay. That works fine when I run a test like this ...
<select data-val="true"
data-val-mustbe="You must select a value"
data-val-mustbe-condition="0"
data-val-mustbe-propertyvalue="default"
data-val-required="You must select a value"
id="select_value">
<option value="default">Choose...</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
Very simple. It works exactly as I expect. So I then go to apply this to my Knockout View Model - I change the code to look like this. I seem to have to have the "optionsValue" in order to have something for the validator to wire into.
<select
data-bind="options: Actors, optionsText: 'Name',
value: Actor, optionsCaption: 'Choose an actor ...', optionsValue: 'Id'"
data-val="true"
data-val-mustbe="You must select an actor"
data-val-mustbe-condition="0"
data-val-mustbe-propertyvalue=""
data-val-required="You must select an actor" ></select>
The basic output looks the same - and the validation seems to work, but now there is a change. Whenever the user makes a selection from the select list, the resultant view model looks totally different. It looks like this ...
{
"Actor": "actors/1",
"Actors": [
{
"Id": "actors/1",
"Name": "Character 1",
"Tags": null
},
{
"Id": "actors/2625",
"Name": "Character 2625",
"Tags": null
}
]
}
It only passes the actor's id through the field, instead of both the name and id. This is, of course, causing the behavior to not work as I desire.
Any ideas?