Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remote validation and init #180

Open
jakubsacha opened this issue Nov 28, 2012 · 7 comments
Open

Remote validation and init #180

jakubsacha opened this issue Nov 28, 2012 · 7 comments

Comments

@jakubsacha
Copy link

Hey,

i have:

function orderViewModel(data){    
    var self = this;
    this.id = ko.observable(data.id);
    this.date = ko.observable(data.date).extend({
        remote: {
            data: {
                'form':'AddOrder',
                'field':'date',
                'id':self.id()
            }
        }
    });
    this.description = ko.observable(data.description).extend({
        remote: {
            data: {
                'form':'AddOrder',
                'field':'description',
                'id':self.id()
            }
        }
    });
    this.status = ko.observable(data.status);

    this.isValid =  ko.computed(function(){
        return ko.validation.group(this);
    }, this);
}

but when my app stats, becouse i print list of models, i've got many validation requests in background (it laqqs a lot). i cant find possibility to disable validation during initialization. could someone show me correct way?

@fbuchinger
Copy link

@jakubsacha ko.validation seems to execute the validator rules when you assign it to observables with values (i.e. non falsy-values like "", null, etc). I'm afraid you have to monkey-patch ko.validation.js to turn off this behaviour for remote validations. or has anybody other ideas?

@jakubsacha
Copy link
Author

i've tried firsly initize model, and then attach validators. but with no success. it works same - validator sends a lot of requests. does anybody see some simple solution how to handle this?

im quite new in knockout and ko.validation im not sure i'm able to patch it my own.

@fbuchinger
Copy link

maybe it can help to use the onlyIf parameter:

var afterInitialize = false;
var description = ko.observable(data.description).extend({
        remote: {
            data: {
                'form':'AddOrder',
                'field':'description',
                'id':self.id()
            },
            onlyIf: function (){
               return afterInitialize;
           }
        }
    });
//initialize all obserables of your model here

afterInitialize = true;

@jakubsacha
Copy link
Author

almost! :-)

validator is lunched as i expected (onkeyup) but:

ko.validation.rules['remote'] = {
    async: true,
    validator: function ( val, parms, callback ) { 
       // here parms are always 'true', instead of data passed from model
        });

    },
    message: 'Błędne dane'
}; 

@jakubsacha
Copy link
Author

okey, final working code:

function orderViewModel(data){    
    var self = this;
    var afterInitialize = false;
    this.id = ko.observable(data.id); // i do not validate this field
   // fields, like below:
    this.description = ko.observable(data.description).extend({
        remote: {
            params: {
                'form':'AddOrder',
                'field':'description',
                'id':self.id()
            },
            onlyIf: function (){
                return afterInitialize;
            }
        }
    });
    this.status = ko.observable(data.status);

    afterInitialize = true;

    this.isValid =  ko.computed(function(){
        return ko.validation.group(this);
    }, this);
}

and ajax validator:

ko.validation.rules['remote'] = {
    async: true,
    request: new Array(),
    timeouts: new Array(),
    validator: function ( val, parms, callback ) { 
        var self = this;
        var ajaxKey = 'default';
        if(parms.field != null){
            if(parms.id != null){
                ajaxKey = parms.field+parms.id;
            }
            else{
                ajaxKey = parms.field+'_new';
            }
        }
       // abort existing request
        if(self.request[ajaxKey] != null){
            self.request[ajaxKey].abort();
        }
        var options = {
            url: '/validators/validate',
            type: 'POST',
            dataType: 'json',
            success: callback,
            data: $.extend( parms, {
                'value':val
            })
        };

        // decrease amount of request. delay them by 200ms
        clearTimeout(self.timeouts[ajaxKey]);
        self.timeouts[ajaxKey] = setTimeout(function(){
            if(self.request[ajaxKey] != null){
                self.request[ajaxKey].abort();
            }
            self.request[ajaxKey] = $.ajax( options );
        },200);

    },
    message: 'Błędne dane'
}; 

my ajax validator supports aborting existing ajax requests for each field. they are also delayed by 200ms to decrease requests amount.

ajax request returns json like this:

{"isValid":true,"message":""}

and for error:

{"isValid":false,"message":"Something is wrong!"}

thanks guys.

@fbuchinger
Copy link

@ericmbarnard is there a more elegant way to prevent initial remote validation? The above approach feels a bit clumsy

@stevegreatrex
Copy link
Contributor

How about using the isModified flag?

var ViewModel = function() {
    var self = this;
    this.description = ko.observable("initial value").extend({
        remote: {
            data: {},
            onlyIf: function() { 
                return self.description && self.description.isModified();
            }
        }
    });
};

It's still not beautiful, but it needs less code. You can see a working example here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants