Knockout Custom Validation with an observable parameter

11,061

Solution 1

I have now managed to figure this out using the following code:

Create a custom validator function

var customMax = function(val, max) {
    return val <= max();
};

Pass the validation function and wrap the message in a function

var SpecifiedValuablesViewModel  = function (maxSpecifiedItemAmount) {
    var self = this;

    self.maxSpecifiedItemAmount = ko.observable(maxSpecifiedItemAmount);

    self.amountToAdd = ko.observable().extend({
        validation: {
            validator: customMax,
            message: function () { return 'The maximum allowed is ' + self.maxSpecifiedItemAmount(); },
            params: self.maxSpecifiedItemAmount
        }
    });

    self.maxSpecifiedItemAmount.subscribe(function (amount) {
        self.amountToAdd.isModified(false);
    });
};

var specifiedValuablesViewModel = new SpecifiedValuablesViewModel($('#ContentsReplacementAmount').val());
ko.applyBindings(ko.validatedObservable(specifiedValuablesViewModel), document.getElementById('SpecifiedValuables'));

$('#ContentsReplacementAmount').on('change', function () {
    specifiedValuablesViewModel.maxSpecifiedItemAmount(parseInt($(this).val()));
});

JSFiddle example

Solution 2

This is a shot in the dark since I'm not all that familiar with the validation plugin, but try

    validation: {
        validator: function (val, max) {
            return val <= max();
        },
        message: 'The amount must be a maximum of £{0}',
        params: self.maxSpecifiedItemAmount
    }

This way you're passing the observable itself, rather than its value, as your validation parameter and evaluating it when the validator function is invoked rather than when the rule is defined.

Share:
11,061
Stokedout
Author by

Stokedout

Updated on June 12, 2022

Comments

  • Stokedout
    Stokedout about 2 years

    I have a situation where I need to validate the max amount of a field in my view model. However the max amount has to be variable and is calculated depending on a UI item selected outside of this model. I have attempted to include the observable as a parameter in my custom validator but it appears not to update when the value is changed.

    I have a feeling that once the validation code is executed first time it holds on to the parameters.

    The HTML of the list that's not using Knockout

    <select id="ContentsReplacementAmount">
        <option value="25000">£25000</option>
        <option value="50000">£50000</option>
        <option value="75000">£75000</option>
    </select>
    

    Here is a dummed down version of the code I'm using.

    var SpecifiedValuablesViewModel = function (maxSpecifiedItemAmount) {
        var self = this;
    
        self.maxSpecifiedItemAmount = ko.observable(maxSpecifiedItemAmount);
    
        self.amountToAdd = ko.observable().extend({
            validation: {
                validator: function (val, max) {
                    return val <= max;
                },
                message: 'The amount must be a maximum of £{0}',
                params: self.maxSpecifiedItemAmount()
            }
        });
    };
    
    var specifiedValuablesViewModel = new SpecifiedValuablesViewModel($('#ContentsReplacementAmount').val());
    ko.applyBindings(ko.validatedObservable(specifiedValuablesViewModel), document.getElementById('SpecifiedValuables'));
    

    Event outside of the maxSpecifiedAmount

    $('#ContentsReplacementAmount').on('change', function () {
        specifiedValuablesViewModel.maxSpecifiedItemAmount(parseInt($(this).val()));
    });
    

    My question is, how can I achieve this?