2

The following is a view models in ASP.NET MVC:

public class Email
{
  public string Selected { get; set; }
  public string Name { get; set; }
}
public class User
{
  public string UserName { get; set; }
  public IList<Email> Emails { get; set; }
}

It is passed into the view and looks like this while defining the knockout view model:

var viewModel = {
  UserName: ko.observable("@Model.UserName"),
  Emails: ko.observableArray(@Html.Json(@Model.Emails) || []),
  // many other things
}

I want to make sure that Email.Selected is required. How to do it having the list, rather than single objects. I know it must be the easiest question, but I couldn't find anything on the topic.

I use knockout validation on the client, since Fluent and data annotation aren't working with knockout unfortunately.

Display Name
  • 4,672
  • 1
  • 33
  • 43
  • Do you want to enable client-side validation? The type used by the MVC framework through jQuery? – rae1 Mar 12 '13 at 00:49
  • @rae1n Good question - I will edit my question. Data Annotation and Fluent Validation **unfortunately** do not work in knockout context (teach me otherwise if you know something). Hence I must use jQuery or Knockout validation. I opted for the latter. I know how to express required for single element, but I get full List from the server - not sure how to handle that. Thanks. – Display Name Mar 12 '13 at 00:57
  • The reason I ask is because I saw a previous question where you mentioned `knockout-validation.js`; however, I only know how to trigger validation for arrays/lists using jQuery's validation. – rae1 Mar 12 '13 at 01:15
  • 1
    You can use `Knockout custom validation (https://github.com/ericmbarnard/Knockout-Validation)` for your purpose. – Gaurav Mar 12 '13 at 02:52

1 Answers1

2

As i mentioned on my comment knockout custom validation can helps, here i am adding an example of how to use knockout custom validation in your case :

var viewModel = {
  UserName: ko.observable("@Model.UserName"),
  Emails: ko.observableArray(@Html.Json(@Model.Emails) || []).
          extend({
             customRequired: { message: 'Selected is required' }
          });

  // many other things
}


ko.validation.rules['customRequired'] = {
    validator: function (emailList) {
        var pass = true;
        ko.utils.arrayFirst(emailList(), function(email){
           if(email.Selected == '')       //if Selected property is empty
           {
             pass = false;
             return true;                 //break the loop
           }
        });
       return pass;
    }
};
Gaurav
  • 8,367
  • 14
  • 55
  • 90
  • Thanks for comment (+1), thanks for solution (coming). I still don't know how to express C# object `List` inside the comment part you left in (hence I provided the MVC view model to look at). Would you mind accessing `Selected` property inside Email in JS code (sorry, I am relatively newby) - this is why asking. Thanks! – Display Name Mar 12 '13 at 03:08
  • 1
    Inside custom validator emailList will be the observableArray, check updated answer – Gaurav Mar 12 '13 at 03:26
  • That easy!? Thank you very much, let me test, I'll be back. I should learn java script one day :) – Display Name Mar 12 '13 at 03:28
  • From what I understand you checking the entire array to have Selected not empty. I was looking for declaratively express that mr. Selected should be required, something like `Selected: ko.observable().extend({ required: true })` or smth like that... Similar to data annotations in MVC. Is that possible? – Display Name Mar 12 '13 at 03:30
  • `Selected should be required: true or smth like that..` by this you mean to say Selected should be required true for all objects in the array or atleast 1 ? – Gaurav Mar 12 '13 at 03:40
  • For all. The whole point of exercise is for user to label every email he punches in as "home"/"work"/"personal" etc. So when he submits, before going to server, on the client side he will have red around every label he didn't select and error message. Instead of functional solution (looping) I was looking for more elegant, declaratively express what's required, what should be what length etc instead of running some functions . Hope you following ... Thanks – Display Name Mar 12 '13 at 03:44
  • If i understand correctly than you should create a new object email in javascript and your current viewmodel contains the list of email object (exact similar structure which you have on server). Than you can apply rules on Selected or other properties in email object. – Gaurav Mar 12 '13 at 03:51
  • I think you solved the problem with custom validator. As for me, I will rephrase the question cause I was looking for declarative solution. If you know Data Annotations in ASP.NET MVC for every property you want validated you define what validations apply and both server and client are validating it out of the box, its just that knockout knocks it out and validations don't work anymore. If it wasn't array - its trivial, extend every property and define what you want, its the array that I don't know how to handle. Thank you very much. – Display Name Mar 12 '13 at 03:55