1
votes

I have a model which contains a multi select and a text box.

I want a validation to show up if none of them are populated, but no validation error if at least one of them is populated. (either one item in the select clicked, or some text).

I have a working plunkr here: plnkr.co/edit/pwKohFTmLPW1BKNwHxWR?p=preview

I tried thousands of things with no success. The problem at its core is that self.isValid() does not trigger the validation function SubscribersOrEmails

Currently I have this:

var ReportSchedule = function () {

   self.Subscribers = ko.observableArray().extend({ required: { onlyIf: function () { return self.SubscribersOrEmails === 0; } } });
   self.Emails = ko.observableArray().extend({ required: { onlyIf: function () { return self.SubscribersOrEmails === 0; } } });
   self.EmailText = ko.observable();

   self.SubscribersOrEmails = ko.computed(function () {
            var counter = 0;
            if (self.Emails != null && self.Subscribers != null) {
                counter = self.Emails().length + self.Subscribers().length;
            }
            console.log("counter: " + counter);
            return counter;
        });
}

I tried custom validators and every combination under the sun.

Any ideas what to try next?

I am using knockout v3.2.0-beta

1
{ onlyIf: function () { return self.SubscribersOrEmails === 0; } You have to call the observable with brackets self.SubscribersOrEmails() - Tsvetomir Nikolov
I'm pretty sure that's not correct for computed functions. Examples I found online don't require brackets. If I add the brackets you get: self.SubscribersOrEmails is not a function - Nick
ko.pureComputed is not a function I think it's a different knockout version there. But I tried a similar method which didn't work - Nick
No it's not but I didn't post the full code cause it's thousands of lines. Everything works perfectly well except the dependency validation. I would produce a plunkr but it would take hours - Nick
You can have all the code. I'll post a plunkr in the question. But it's obviously not a working plunkr. That would take many hours to produce - Nick

1 Answers

0
votes

This should solve it. Your computed expects the variables to exist, and your validation routine expects the computed to exist, so you need to separate the variables from their extensions.

You were checking in the computed for whether the variables existed, but that prevented Knockout from figuring out the dependency.

The required argument can just be self.subscribersOrEmails, you don't need to wrap it in a function.

self.Subscribers = ko.observableArray();
self.Emails = ko.observableArray();
self.EmailText = ko.observable();
self.Name = ko.observable();

self.SubscribersOrEmails = ko.computed(function() {
  console.log("validation ");
  var counter = 0;

  console.log(self.Emails);
  console.log(self.Subscribers);
  counter = self.Emails().length + self.Subscribers().length;
  console.log("counter: " + counter);
  return counter == 0;
});

self.Subscribers.extend({
  required: {
    onlyIf: self.SubscribersOrEmails,
    params: 'Subscribers'
  }
});
self.Emails.extend({
  required: {
    onlyIf: self.SubscribersOrEmails,
    params: 'Emails'
  }
});

Also: you were overwriting Emails instead of setting its contents here:

self.populateEmails = function() {
  self.Emails(self.getEmailsFromText(self.EmailText()));
}

And also here:

$.each(self.schedulesViewModel.Schedules, function(index, schedule) {
  var emailsArray = schedule.getEmailsFromText(schedule.EmailText());
  schedule.Emails(emailsArray);
});

The error messages never get cleared because you have no code to clear them.