How to do a validation that requires an API call

I want to add a validation to make sure the email address added to a record is unique.  This, of course, requires an API call to go check the current email address to all the others.  The problem is, in my validation function, by the time the API call returns the record is saved already.

I am looking to see if anyone else has already conquered this.  I have already tried changing the "{async: true}" to "{async: false}".  Not sure what that does but it doesn't fix this.

For example if this were my function (maybe better written in the end), by the time the 'Success' function was triggered, the record is already saved.

_doValidateEmail: function (evt) {
     // let emails = $(".existingAddress").val(),
     let self = this,
            id = this.model.get('id'),
            emailField = this.$(evt.currentTarget);
        $(".newEmail, .existingAddress").each(function () {
             let emailAddress = $(this).val(),
                urlString = 'uniqueEmail/' + id + '/' + emailAddress;
            if (!self.isEmptyS2S(emailAddress)) {
                 if (emailAddress.indexOf('.') > 0) {
                      console.log('Testing email address: ' + emailAddress);
                      console.log('URL: ' + urlString);
                      App.api.call('GET', App.api.buildURL(urlString),
                        {}, {
                           success: function (data) {
                                let contact=data.split('|');
                                if (self.isEmptyS2S(data) && red === false) {
                                     console.log('GREEN');
                                     emailField.css('color', 'green');
                                     App.config.validEmail='';
                                } else {
                                     console.log('RED');
                                     console.log(data);
                                     console.log(contact[0]);
                                     console.log(contact[1]);
                                     emailField.css('color', 'red');
                                     red = true;
                                          errors['email'] = errors['email'] || {};
                                          errors['email'].required_validation = true;
                                     App.config.validEmail=[contact[0],contact[1]];
                                     app.alert.show('not_unique_email', {
                                        level: 'error',
                                        messages: app.lang.get('ERROR_POPUP_EMAILMUSTBEUNIQUE', 'Contacts', {name: contact[0]}),
                                        autoClose: false
                                    });
                                }
                            },
                           error: function (e) {
                                console.log('error');
                                console.log(e);
                           }
                      }, {async: true});
                }
            }
        })
    }
  • Hi Kenneth Brill,

    Why don't you use this.model.addValidationTask and write your validation script under that?

    This way, you can wait for your API to come back with response and then return the callback.

    this.model.addValidationTask('validate_email', _.bind(this._doValidateEmailAddress, this));

    Let us know if this helps.

  • consider the following example. In this example we add a validation task that checks a certain account number field. In the success/error callbacks we execute the callback that we initialy received from the validation method. 

    // initialize method of the create/record.js

    this.model.addValidationTask('check_accountnumber',_.bind(this._doValidateAccountNumber,this));

    // the actual validation method:
    _doValidateAccountNumber: function(fields, errors, callback){
    console.log('validate account number');
            let acnumber = this.model.get('accountnumber_c');
            if(!_.isEmpty(acnumber) && !_.isUndefined(acnumber)){
                let options = {async: false};
                let url = app.api.buildURL('accounts','number/'+acnumber);
                app.api.call('read',url,options,{
                    success: _.bind(this.onValidAccountNumber,this,fields,errors,callback),
                    error: _.bind(this.onInvalidAccountNumber,this,fields,errors,callback)
                });
            }else{
                callback(null, fields, errors);
            }
        },


    onValidAccountNumber: function(fields,errors,callback){
            callback(null, fields, errors);
    },

    onInvalidAccountNumber: function(fields,errors,callback){
      errors['accountnumber_c'] = errors['accountnumber_c'] || {};
      errors['accountnumber_c'].account_number_duplicate_msg = true;
      callback(null, fields, errors);
    },