Troubleshooting problems with AJAX call in custom validation for Knockout JS

I have created a custom validation function that checks whether a zip code entered in a form field is valid for the selected state from a dropdown. The validation works correctly when I initially select a state and then input a zip code, but if I change the state after validation, the error message does not reappear. Can someone help me understand why it's not re-validating?

Custom Validation:

ko.validation.rules["isValidZipCode"] =
    {
        async: true,
        getValue: function (o) {
            return (typeof o === 'function' ? o() : o);
        },
        validator: function (val, fields, callBack) {
            var self = this;
            var anyOne = ko.utils.arrayFirst(fields, function (field) {
                var val = self.getValue(field);

                if (val === undefined || val === null) 
                    return "";                
                return true;
            });

            var ajaxData = { state: anyOne, zipCode: val }
            $.ajax({
                url: $("a#ValidateZipByState").attr("href"),
                type: "POST",
                data: ajaxData,
                success: function (isValid) {
                    if (isValid) {
                        callBack(true);
                    } else {
                        callBack(false);
                    }
                },
                error: handleSubmitError
            });

            return;
        },
        message: "Invalid zip code for this state"
    };

ViewModel:

self.State = ko.observable(model.State).extend({ required: true });
self.ZipCode = ko.observable(model.ZipCode).extend({ required: true, pattern: /^[0-9]{5}(?:-[0-9]{4})?$/g, isValidZipCode: [self.State, self.ZipCode] });

Answer №1

To ensure validation on ZipCode in State subscriptions, utilize the ko.validation.validateObservable method. For specific ZipCode rules, consider implementing an anonymous custom rule.

self.State = ko.observable("StateB").extend({ 
    required: true
});

self.State.subscribe(function(){
    ko.validation.validateObservable(self.ZipCode);
})

self.ZipCode = ko.observable(789).extend({
    validation: {
        async: true,
        validator: function (val, params, callback) {
            setTimeout(function() {
                var zips = stateZips.get(self.State());
                var exists = zips.some(function(zip) {
                    return zip == new Number(val);
                });
                return callback(exists);
            });
        },
        message: "Invalid zip code for this state"
    }
});

Check out the complete example link here: JSFiddle

EDIT: To enable State to trigger validation without changing ZipCode first, use:

ko.validation.init({ messagesOnModified: false });

Answer №2

It appears that the validation rule is specifically linked to the ZipCode observable, meaning that altering the State value alone will not prompt a new validation. To trigger an update, you would need to modify the state first and then adjust the zipcode as well. This workaround may help resolve the issue:

self.State.subscribe(function(newValue){
    self.ZipCode.valueHasMutated();
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ensuring a form is required using ng-validate

A sample form structure is shown below: <div class="row" id="yesAuth"> <div class="col-md-6" ng-class="{ 'has-error': invalid.basicAuthForBackendUsername, 'has-success': valid.basicAuthForBackendUsername}"> < ...

Ways to Soothe Long Polling

Currently, I am developing a basic chat feature using AJAX in a function that triggers a setTimeout call to itself upon successful execution. This occurs approximately every 30 seconds. While this setup serves its purpose, I am seeking a more immediate not ...

Using jQuery to prepend elements and then fade them in

Whenever a user makes a post, it should be displayed at the top of the feed page with a nice fadeIn effect. However, my current script seems to hide all the updates before showing them again. I only want this effect to apply to the latest status. What cou ...

Utilizing the hint operator in strongloop loopback with mongoDB: A step-by-step guide

Seeking guidance on utilizing the hint operator from mongodb within Strongloop Loopback. While I have successfully implemented this operator directly in mongodb, navigating its use within Strongloop Loopback has proven challenging. Any advice on how to int ...

Incorporating an external SVG link into a React application

While I may not be an SVG expert, I haven't encountered any issues with loading SVGs in my React app so far. I prefer using the svg tag over the image tag because sizing tends to present problems with the latter option when working with external links ...

Issue encountered while appending new rows to the tbody of a table

I'm encountering an issue with the append function within a for loop in my code. The string being passed to the function isn't parsing correctly and results in an error. How can I go about resolving this problem? Thanks! function getDetailPopUp ...

Error: Unrecognized primary operator: $sortby

We have a web application built using Node.js and Mongoose, running on Ubuntu Linux servers hosted on DigitalOcean VPS. One of our Mongoose queries includes a text index with the following operators: less than / equal to limit order by This is how the ...

Issue with React-Axios: File data being sent to Node server is undefined

My current challenge involves uploading a single file and saving it in a specific folder within my app directory. While I can successfully choose a file on the frontend and update the state of the Uploader component, I encounter an issue when sending a POS ...

Trouble arises when implementing personalized buttons on the Slick JS slider

Are you struggling to customize buttons for your Slick Slider JS? I am facing a similar issue with applying my own button styles to the slider. I am interested in using arrow icons instead of the default buttons. Here is the HTML code snippet: <secti ...

Focus on the image displayed through instafeed.js

Using the Instafeed.js plugin to create a dynamic Instagram feed. Everything is working smoothly, but I'm struggling to center the images being retrieved by Instafeed. Despite trying various methods, I can't seem to get it to display as desired. ...

Is there a method to implement a pop-in animated contact form without the use of Javascript or query selectors?

Although I was successful in creating a contact form with this functionality using Javascript, I encountered some difficulties when attempting to achieve the same result without it. My goal is for the form to slide in from the right when the "open" icon is ...

Utilize the ng-click feature for swiping interactions in Ionic v1

I have a slide page on Ionic V1 that utilizes previous and next buttons. Here is an example: <button id="" class="button button-slide prev no-animation" ng-click="prev()" ng-show="activeIndex > 0" > BACK </button> While the click function ...

Limiting the use of JavaScript widgets to specific domains

In the process of developing a webservice that offers Javascript widgets and Ajax calls limited to specific domains, I have explored various options. However, my research has led me to consider using a combination of HTTP-Referer and API Keys for access ...

Struggling to configure an onClick handler in Next.js

Unexpectedly, I was met with a surprise while trying to access react.dev, as it stated that create-react-app is no longer recommended for bootstrapping React applications. No worries, the world is always evolving. Let's explore Next.js for my first p ...

`Turn a photo into a circular shape by cropping it`

Even though I know that the solution involves using border-radius: 50%, it doesn't seem to be working for my situation. In my code using React/JSX notation, this is how the icon is displayed: <i style={{ borderRadius: '50%' }} className= ...

Guide to simulating an option tag selection in a rb file

Visit the WTA website's rankings page to see the top 100 tennis players. Utilizing the <option> tag in conjunction with the <select> tag allows users to select groups of players ranked between 101 and 200, and so forth in increments of ...

What is the method for accessing HTML tag data within a script?

Looking for a way to extract a specific substring from a given string: var str = `<ul class="errorlist"><li>Enter a valid email address.</li></ul>`; Is there a method to extract the following substring? 'Enter a valid email ...

Create a Vue application that is built on modules which could potentially be absent

I am currently developing a Vue+Vite app with module-based architecture. I have several Vue components and some parts of the app are functioning correctly. However, I want to ensure that the missing components are not imported or used in the application. H ...

JavaScript, keep it easy: globalize

Looking for help with a simple regex expression... document.getElementById('testing').value=f2.innerHTML.replace(">",">\n"); I'm having an issue where it only stops after the first line break. How can I make it work for the enti ...

document ready function in the Microsoft AJAX client side library

The Microsoft AJAX client-side library contains various functions that imitate the server-side Page Life Cycle and conditions like if (!Page.IsPostBack). I am unsure about which client-side function corresponds to the equivalent server-side method. What is ...