overriding Save button : after ajax validation save editView form

Hello everybody!!

You may have noticed that this thread is a duplicate one of Sugar 7 bwc overriding Save button to add ajax but i don't know why but the forum did a mess with it and repeated everything several times (Hey @Sugar Staff, i didn't find somewhere to talk about it).

So, here is again my problem, with better construction and further precision.

What i want :

I want sugar to check if the assigned user already have meetings planned WHEN the current user clicks on Save button.

What i did :
I've overrided the Save button by doing this custom code under custom/modules/Meetings/editviewdefs.php :

array (            'customCode' => '<input title="{$APP.LBL_SAVE_BUTTON_TITLE}" id ="SAVE_HEADER" accessKey="{$APP.LBL_SAVE_BUTTON_KEY}" class="button primary" onclick="SUGAR.meetings.fill_invitees();return validationPlanification();document.EditView.action.value=\'Save\'; document.EditView.return_action.value=\'DetailView\'; {if isset($smarty.request.isDuplicate) && $smarty.request.isDuplicate eq "true"}document.EditView.return_id.value=\'\'; {/if} formSubmitCheck();" type="button" name="button" value="{$APP.LBL_SAVE_BUTTON_LABEL}">',
          ),

you can see it is calling a js function, which is below and is defined under customjs.js (this last is included in editviewdefs too)

function validationPlanification(){ if($("#status").val()=="Planned"){
  var user_id = $("#assigned_user_id").val();
  var user_name = $("#assigned_user_name").val();
 
  var duration_h = $("#duration_hours").val();
  var duration_m = $("#duration_minutes").val();
  var date_start = $("#date_start_date").val()+" "+$("#date_start_hours").val()+":"+$("#date_start_minutes").val();
 
  var href = $(".moduleTitle").find('h2 a').attr('href');//trouver le lien du record
  if (href != undefined){
   var idx = href.indexOf('record');//trouver où se situe le mot "record"
   var bean_id = href.substr(idx+7);//chopper l'id
  }else{
   var bean_id = '';
  }

  var ajax = $.ajax({
   url: "http://&lt;Sugarbase&gt;/index.php?entryPoint=validateAvailability",
   type: "POST",
   data: { userid : user_id, beanid : bean_id, date : date_start, h : duration_h, m : duration_m},
   success: function(data){
    //console.log(data);
    if (data === "false"){
     console.log("nok");
     alert("L'utilisateur "+user_name+" a déjà d'autres rendez-vous de prévus sur cette plage horaire!");
     //on ne peut pas sauvegarder
     return false;
    }
    if (data === "true"){
     console.log('ok');
     //return true;
     return check_form('EditView');
    }
   },
   error: function(){
    //console.log(data);
    console.log("SQL Failure");
   }
  });
}
}

you can see this function is doing an ajax call to a custom entrypoint. this works (tested it by setting some log at the beginning of the entry point) this entrypoint is querying the base to know if the assigned user already have a meeting set. It returns $is_available = true if the user does not have a meeting. else, it returns$is_available = false.
This works, i've set some console.log(data) when the ajax call is a success.

Then, you can see i'm testing the data retrieved. if data is true, so Sugar must save the current editview form. and if it is false, i think i'll throw an alert.

What is not working :
Everything works fine until i try to save the editview form : my return check_form('EditView') does not work, neither a simple "return true".

Do you have any idea on that?

Thanks a lot for the long reading, and your time.
Gaëlle


Parents
  • The way I do this sort of thing is have a custom js file

    In it I have a function check_form which overwrites the standard sugar one so you don't need to play with editviewdefs apart from including the custom js file

    something like

    function check_form(formname) {
    /*
      * replace main check_form standard sugar validation plus your changes
      */

    //standard validation
    if (ValidateForm(formname) == false) return false;

    //your validation
    if (yourfunction() == false) return false;

    return true;
    }

    If you are doing an ajax call for validation I would do a synchronous call 

    Hope this helps
  • SO, this thread can be closed, it is totally SOLVED (yaaaayyy!)
    Thanks to @Enrico Simonetti and @Mike Solomon who gave me a lots of advices, and more awesome : working advices!

    Here is the code for those who would run in this problem :

    Don't override Save button custom code in custom/modules/Meetings/metadata/editviewdefs.php : the Save button will check for the function check_form('EditView'), all by itself.

    Just override check_form() function in a custom js file :
    in custom/modules/Meetings/js/customjs.js (create one, the folder name and the file name could be anything), write those two functions :

    function validationPlanification(){
    if($("#status").val()=="Planned"){
         var user_id = $("#assigned_user_id").val();
         var user_name = $("#assigned_user_name").val();
     
         var duration_h = $("#duration_hours").val();
         var duration_m = $("#duration_minutes").val();
         var date_start = $("#date_start_date").val()+" "+$("#date_start_hours").val()+":"+$("#date_start_minutes").val();
     
         var href = $(".moduleTitle").find('h2 a').attr('href');//trouver le lien du record
         if (href != undefined){
               var idx = href.indexOf('record');//trouver où se situe le mot "record"
               var bean_id = href.substr(idx+7);//chopper l'id
          }else{
               var bean_id = '';
          }

          var ajax = $.ajax({
               url: "http://&lt;baseSugar&gt;/index.php?entryPoint=validateAvailability",
               async : false,
               type: "POST",
              data: { userid : user_id, beanid : bean_id, date : date_start, h : duration_h, m : duration_m},
              success: function(data){
                    if(data > 0){
                         alert("L'utilisateur "+user_name+" a déjà d'autres rendez-vous de prévus sur cette plage horaire!");
                     }
              },
              error: function(){
                  console.log("SQL Failure");
              }
          });
       return ajax.responseText;
     }
    }


    function check_form(formname) {
    /* OLD VERSION : not making required fields required states. */
       if (validationPlanification() > 0){
            return false;
        }else{
             return true;
       }
    /* END OLD VERSION*/
    /*NEW VERSION so cool!*/
        if (typeof(siw) != 'undefined' && siw  && typeof(siw.selectingSomething) != 'undefined' && siw.selectingSomething)
           return false;
        return validate_form(formname, '');

        /*launching assigned_user availability validation*/
        if (validationPlanification() > 0){
             return false;
        }else{ 
             return true;
         }
    /*END NEW VERSION*/
    }

    The function validationPlanification will do a synchronous ajax call to a php file which i've defined as a custom entryPoint (because it was the only solution i found)

    This php file runs a sql query which sort all meetings'id (EXCEPT the current meeting id) related to the assigned user and whose date_start and date_end are between the date_start define by the user and the date_start + the duration gave by the user.

    Then, i count the number of rows of the result. and i return this number of rows to the ajax call.
    When i got my data, if the number is > 0, i throw an alert to the sugar user. Then, after the ajax call, and because it is synchronous, i return the responseText.


    Now for the custom check_form(), i just run the validationPlanification function. this one returns me the number of rows. I check if this one is >0, if yes, i return false : the editView form won't be submitted and saved. If else, it will.

    And that is all. Thanks a lot to this wonderful sugar community!!!
    ---------
    EDIT 18h : Because of the previous version (becareful, in the code snippet, i've edited the "old version" and gave you the new one), i couldn't have my required field launching some errors and tunring red.
    But @Mike Solomon saved the day by helping me out with that.

    In fact, before launching your own custom validation function, you have to copy/paste the snippet of code present into the check_form(form_name) function under the file ./include/javascript/sugar_3.js.
    Code edited! :)


    That's all folks!
    Have a nice week end!






  • Hi GaelleFernandez,

    Why are you doing an synchronous request when you can do an async one instead?
    It would be a hassle for your end user and in some ways degrade your user experience.
    Also if memory serves me right if async is set to false then this freezes the screen until the result comes back. So here is my attempt at revising your code, just outlined the methods not copy all your code:

    var isProcessing = false;
    function check_form(formname){
        if(isProcessing === true){
           alert('form validation still in progress');        //replace with a custom alert you want
        }
        //do your validation here
        validationPlanification();
       return false;
    }
    function validationPlanification()
    {      isProcessing = true;
          //do some more validation
          // show a loading message here
         $.ajax({
            url: "your url",
            type: POST | GET,
            data: {some data here}
            success: function(data){             isProcessing = false;
                //remove loading message
                if(data == true){
                      submitForm();
                }
            },
            error: function(error)
             {                  isProcessing = false;
                    //display error message
             }
         })
    }
    function submitForm()
    {
            //use jquery to submit your form here
    }

    this is just a suggestion for when using ajax asynchronously.

    Hope this helps
Reply
  • Hi GaelleFernandez,

    Why are you doing an synchronous request when you can do an async one instead?
    It would be a hassle for your end user and in some ways degrade your user experience.
    Also if memory serves me right if async is set to false then this freezes the screen until the result comes back. So here is my attempt at revising your code, just outlined the methods not copy all your code:

    var isProcessing = false;
    function check_form(formname){
        if(isProcessing === true){
           alert('form validation still in progress');        //replace with a custom alert you want
        }
        //do your validation here
        validationPlanification();
       return false;
    }
    function validationPlanification()
    {      isProcessing = true;
          //do some more validation
          // show a loading message here
         $.ajax({
            url: "your url",
            type: POST | GET,
            data: {some data here}
            success: function(data){             isProcessing = false;
                //remove loading message
                if(data == true){
                      submitForm();
                }
            },
            error: function(error)
             {                  isProcessing = false;
                    //display error message
             }
         })
    }
    function submitForm()
    {
            //use jquery to submit your form here
    }

    this is just a suggestion for when using ajax asynchronously.

    Hope this helps
Children
  • Gaelle Fernandez Mike Solomon

    Hello,

    I am trying to achieve a functionality similar to what Gaelle wanted to achieve in this thread. I want to override the save button. If the country passed to the API is a valid country, only then should the record be saved. This functionality is correctly getting executed. However if an invalid country is passed, I am getting the error message, but also the success save message, and the record is saved too. I want to prevent the saving of the record if the country is invalid. Please could you kindly give some direction here ?

    Following is my code:

    ../custom/modules/Contacts/clients/base/views/record/record.js : 

    ({
    extendsFrom: 'EditView',

    initialize: function(options) {
    this._super('initialize', [options]);
    this.context.on('button:save_button:click', this.validate_country, this);

    },

    validate_country: function(response) {

    var t = this;
    var currentStreet = this.model.get('primary_address_street');
    var currentCity = this.model.get('primary_address_city');
    var currentState = this.model.get('primary_address_state');
    var currentZip = this.model.get('primary_address_postalcode');
    var currentCountry = this.model.get('primary_address_country');

    var encodedStreet = encodeURI(currentStreet);
    var encodedCity = encodeURI(currentCity);
    var encodedState = encodeURI(currentState);
    var encodedZip = encodeURI(currentZip);

    if(the country is united states){
    // pass a correct country parameter to the API

    passCountry = 'US';

    }
    else{
    // pass a wrong country parameter to the API

    passCountry = 'notUS';
    }


    $.ajax({
    type: 'GET',
    async: 'false',
    url: 'someURL',
    crossDomain: 'true',
    headers: {'key': 'value'},


    success: function(response) {
    cityNow = response.city;
    streetNow = response.street1;
    stateNow = response.state;
    zipNow = response.postalcode;
    countryNow = response.country;

    t.model.set('primary_address_city',cityNow);
    t.model.set('primary_address_street',streetNow);
    t.model.set('primary_address_state',stateNow);
    t.model.set('primary_address_postalcode',zipNow);
    t.model.set('primary_address_country',countryNow);

    if (passCountry === 'US')
    {
    app.alert.show('address-ok', {
    level: 'success',
    messages: 'matches',
    autoClose: false
    });
    }

    },
    error: function(response) {
    if(passCountry === 'notUS'){
    app.alert.show('address-ok', {
    level: 'error',
    messages: 'do not match',
    autoClose: true
    });
    }
    }

    })
    }

    })

    Thank you in advance!

  • Try leveraging the handleSave that is already in the view and triggered when Save is clicked:

    in Record View

      handleSave: function(){
        var passCountry = <your function to check the country>;

        if(passCountry != 'US'){
           //this is in the original view and handles the canceling of the action, we never call the parent handleSave that does the actual saving.
          this.handleCancel();
        }else{
          //call the parent handleSave as if nothing happened
          this._super('handleSave');
        }
      },

    in Create View the functions are named differently,  it should be something like:

     save: function(){
        var passCountry = <your function to check the country>;

        if(passCountry != 'US'){
           //this is in the original view and handles the canceling of the action, we never call the parent handleSave that does the actual saving.
          this.cancel();
        }else{
          //call the parent handleSave as if nothing happened
          this._super('save');
        }
      },

    FrancescaS

  • Thank you Francesca Shiekh. This did help.

    However there is a small issue. I am getting an error when I call the custom function in  handleSave function.

    This is how I go about it:

    handleSave: function(){
    var passCountry = validateCountry();
    if(passCountry != 'US'){
    this.handleCancel();
    }
    else{
    this._super('handleSave');
    }
    },

    The error message is: uncaught reference: validateCountry is not defined.

  • Did you define validateCountry?

    It's your function to check for passCountry, it should return passCountry so that the save can decide whether to pass or fail.

    This may be a better way, in this thread:

    community.sugarcrm.com/.../97397-re-how-to-stop-save-action-if-some-condition-become-false 

    someone else brought up:

    http://support.sugarcrm.com/Documentation/Sugar_Developer/Sugar_Developer_Guide_7.8/User_Interface/Views/Adding_Field_Va… 

    FrancescaS

  • Yes this worked. But the record is saved only if the page is active. If I try to refresh the page, the record seems to be unsaved. When I try to leave the page, I am getting the warning message - "You have unsaved changes. Are you sure you want to leave page and discard changes?"

  • Hola EvilPeri It has been a while but could you help me with this code, everything works for me until submitForm, I use the default function of sugar but it repeats everything again