Alessandro Violante
Alessandro Violante

Reputation: 323

Knockout custom validation: How to check if observable is equal to a specific value?

I'm new with Knockout.js, and I would like to check if a field of my form has a specific value. Actually, I only check if it is required or not. What should I do?

Here's what I have in my html page:

 <div data-bind="visible: !Vm.isValid()" class="text-danger">Fill each field to send data, otherwise show this message</div>

 <input data-bind="enable: Vm.isValid()" type="button" value="Send data!" />

That's what my vm.js file looks like:

 window.Vm = ko.validatedObservable({
     name : ko.observable().extend({ required: true })
 });            

I would make something like this, but I don't know how to do it:

 var found = "found";
 window.Vm = ko.validatedObservable({
    name: ko.observable().extend({
       required: true,
       function: {
          if (this.val() == found)
             return true; // invalid value, can't submit my form
       }
    })
 });

Upvotes: 1

Views: 3304

Answers (3)

mukhtar alam
mukhtar alam

Reputation: 323

I have taken data as ["A","B"], and search based upon the same data.

ko.extenders.required = function(target, overrideMessage) {
    //add some sub-observables to our observable
    target.hasError = ko.observable();
    target.validationMessage = ko.observable();
    target.data = ko.observableArray(["A","B"]);
 		target.found = ko.observable();
    target.foundMessage = ko.observable();
    //define a function to do validation
    function validate(newValue) {
       target.hasError(newValue ? false : true);
       target.validationMessage(newValue ? "" : overrideMessage || "This field is required");
       target.found(target.data().find(function(element){ return newValue==element;}));
       target.found()?target.foundMessage("element has found"):target.foundMessage("element has not found");
    }
 
    //initial validation
    validate(target());
 
    //validate whenever the value changes
    target.subscribe(validate);
 
    //return the original observable
    return target;
};
 
function AppViewModel(first) {
    this.firstName = ko.observable(first).extend({ required: "" });
}
 
ko.applyBindings(new AppViewModel("C"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script>
<p data-bind="css: { error: firstName.hasError }">
    <input data-bind='value: firstName, valueUpdate: "afterkeydown"' />
    <span data-bind='visible: firstName.hasError, text: firstName.validationMessage'> </span>
    <span data-bind='visible: (!firstName.hasError()), text: firstName.foundMessage'> </span>
</p>

Upvotes: 0

Brother Woodrow
Brother Woodrow

Reputation: 6382

I would actually recommend against using the Knockout Validation library, as it hasn't been maintained for years. It's an outdated solution to a problem that doesn't really exist anymore. In 2019 you can just use the form validation that is native to every modern browser. Just put a required attribute on your form fields and the form will not submit if not all required fields have been filled out.

If you want it to be a little more dynamic, you could do something like this:

function ViewModel() {
    var vm = this;

    vm.name = ko.observable();
    vm.required = ['name', 'email'];

    vm.isRequired = isRequired;

    function isRequired(field) {
        return vm.required.indexOf(field) > -1;
    }
}

And use the attr binding to set the required attribute based on the array of required elements in your viewmodel.

<input type="text" data-bind="textInput: name, attr: { required: isRequired('name') }">

Upvotes: 1

adiga
adiga

Reputation: 35259

You can use a custom validator like this (Documentation):

var found = "found";

var Vm = ko.validatedObservable({
  name: ko.observable().extend({
    required: {
      message: "This is a required field",
    },
    validation: {
      validator: (val, paramValue) => {
        // "val" has the value entered in the field
        // "paramValue" has the value set in "params"
        return val === paramValue
      },
      message: "The value is not " + found,
      params: found
    }
  })
});

ko.applyBindings(Vm)
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout-validation/2.0.3/knockout.validation.min.js"></script>

<input type="text" data-bind="value: name" />

Upvotes: 0

Related Questions