How do I prevent Editor from committing changes on Ajax call during presubmit?

How do I prevent Editor from committing changes on Ajax call during presubmit?

pansengtatpansengtat Posts: 66Questions: 26Answers: 1

I have read and checked the example on Editor in regards to using preSubmit event as well as field validation. An Editor instance that I would typically create looks like this:

editor.on('presubmit', function ( event, obj, action ) {
var myEntryID = obj.data.myEntry.ID,
      myStartDate = obj.data.myEntry.StartDate,
      myEndDate = obj.data.myEntry.EndDate;
if (myStartDate > myEndDate) {
    this.field('myEntry.StartDate').error('Start Date is to be earlier than/same as End Date');
    return false;
}

However, the question that I am posting is related to an Ajax call, specifically for success returns and how to manipulate data during the presubmit event. The problem is that after calling the PHP script within my Ajax call, it will always return success. And even if I can force-invoke a header('HTTP/1.0 404 Not Found') in my PHP script upon logic conditions, I still won't be able to return false; on error in the Ajax section of this presubmit event. The Editor form will still commit changes and close the form just briefly after I inserted condition checks to display error messages below some fields.

//--- Ajax call after checking initial validation in Editor on preSubmit ---//
$.ajax(
    {
    url: "php/myEditor_manipulateTable.php",
    data: [
          myEntryID: myEntryID,
          myStartDate: myStartDate,
          myEndDate: myEndDate
    success: function(e){
        if (e === "SUCCESS") {
              $('#divInfo').html(e);
       }
       else {
               editor.field('myEntry.StartDate').error('Someone has already scheduled some hours on this Start Date. Please contact the Admin!');
                return false; //--- Is there a way to attach a preventDefault() here, in case return fails?
      },
     error: function(e){
        editor.field('myEntry.StartDate').error('Someone has already scheduled some hours on this Start Date. Please contact the Admin!');
        return false; //--- Is there a way to attach a preventDefault() here, in case return fails?
      },
    }});

I did explore using e.preventDefault in the Ajax function, but that too didn't prevent Editor from making changes after validation on the Ajax call to the external PHP script. The reason for making this call to an external script is because I don't have the data displayed on the front-end, and the script is validating data on a different table than the one used for the front-end.
So now I would like to know if there is a way to manipulate the Ajax call in such a way that when some conditions in the external PHP script are met, I could intercept presubmit and display the error message as well as prevent this particular Editor instance from committing changes.

This question has accepted answers - jump to:

Answers

  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin
    Answer ✓

    //--- Ajax call after checking initial validation in Editor on preSubmit ---//

    preSubmit is not asynchronous - you can't make an async call inside it and use the async result since the async result will return after the rest of the function has executed and returned.

    There are three options:

    1. Set async: false - you will get warnings in Chrome about this as async: false will be removed in future versions of the XHR spec.
    2. Reflow the code so the async validation is done on input
    3. Change the preSubmit to handle two code paths:
      1. User submit - make Ajax call and return false always. In success you would then call submit with a flag set
      2. When preSubmit is run again, the flag is checked (and cleared for the next time), no Ajax call is made since validation has passed.

    3 is probably the most complicated, but also the most complete solution.

    Allan

  • pansengtatpansengtat Posts: 66Questions: 26Answers: 1
    edited March 2015

    I am trying to decipher solution 3 and am still puzzled.
    When you wrote "in success", are you referring to the success parameter of the submit() method as in the following:

    var flag = 0;
    
    editor.on('preSubmit', function (e, obj, action) {
        if (flag === 1) {
            flag = 0;
        }
    });
    
    var table_edit = $('#theTable').DataTable({
    tableTools: {
    aButtons: [
    {
        sExtends:        'select_single',
        sButtonClass:    'marginLeft',
        fnClick: function () {
            if (table_edit.row('.selected').length !== 0) {
                editor
                    .buttons({
                        fn: function () {
                                this.submit(
                                    function (success) {
                                    },
                                    null,
                                    function (data) {
                                        var reqID = data.data.myEntry["ID"],
                                            startDate_new = data.data.myEntry["StartDate"],
                                            endDate_new = data.data.myEntry["EndDate"],
                                        if (startDate_new > endDate_new) {
                                            editor.error('myEntry.StartDate', 'Start Date should be earlier than or the same as End Date.');
    return false;
                                        } else if (startDate_initial !== startDate_new) {   
                                            $.ajax({
                                                type: "POST",
                                                url: "php/myEditor_manipulateTable.php",
                                                data: {
                                                    reqID:            reqID,
                                                    startDate_new: startDate_new,
                                                    endDate_new:   endDate_new
                                                },
                                                success: function(e) {
                                                    if (e === "success") {
                                                        flag = 1;
                                                    } else {
                                                        flag = 0;
                                                        editor.error('myEntry.StartDate', 'Some hours are already assigned. Please inform the manager.');
                                                        return false;
                                                    }
                                            });
                                        }
                                    return false;
        });
    }]}});
    

    Or are you referring to the success block of the Ajax call within the function(dataCallback) block?

    Minor update: I noticed that the flow of code is that it would execute whatever is inside the function(dataCallback) block except the Ajax call first, followed by preSubmit, then followed by the Ajax call within the function(dataCallback) block. I am not sure what is the cause.

    Another observation: On the submit() code level, even if I were to call the Editor instance to display error messages when validating, using return false in any of the condition checks won't necessarily block execution. Is this expected behaviour?

  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin
    Answer ✓

    When you wrote "in success", are you referring to the success parameter of the submit() method as in the following [...] Or are you referring to the success block of the Ajax call within the function(dataCallback) block?

    Neither :-). The success option of your $.ajax call that you make to perform the validation.

    Do the Ajax validation in preSubmit and the flag decides the code path (i.e. has validation passed or not).

    Allan

  • pansengtatpansengtat Posts: 66Questions: 26Answers: 1
    edited April 2015

    This is what I have written thus far, it appears to be working on my side but I don't know if there is a cleaner way to write this (apart from the logging-to-console statements):

    //--- Intitalize global variables before $(document).ready(function () {...}) block ---//
    var flag_submitSuccess = 0;
    
    //--- Following code block should be inside $(document).ready(function () {...}) block ---//
    editor.on('preSubmit', function (e, obj, action) {
        console.log("preSubmit was just called...");
        var theID = obj.data.myMainTable.ID,
            theStartDate_final = obj.data.myMainTable.DateStart,
            theEndDate_final = obj.data.myMainTable.DateEnd;            
            
        if (theStartDate_final === '') {
            this.error('myMainTable.DateStart', 'This date is required.');
            flag_submitSuccess = 0;
            return false;
        } else if (theEndDate_final === '') {
            this.error('myMainTable.DateEnd', 'This date is required.');
            flag_submitSuccess = 0;
            return false;
        } else if (theStartDate_final > theEndDate_final) {
            this.error('myMainTable.DateStart', 'The Start Date should be earlier than or the same as the End Date.');
            this.error('myMainTable.DateEnd', 'The End Date should be later than or the same as the Start Date.');
            flag_submitSuccess = 0;
            return false;
        } else {
            theStartDate_final = (obj.data.myMainTable.DateStart).toString();
            theEndDate_final = (obj.data.myMainTable.DateEnd).toString();
            
            $.ajax({
                type: "POST",
                url: "php/myEditor_manipulateTable.php",
                data: {
                    theID: theID,
                    theStartDate_final: theStartDate_final,
                    theEndDate_final: theEndDate_final
                },
                success: function (echoReturned) {
                    if (echoReturned === "SUCCESS") {
                        flag_submitSuccess = 1;
                        console.log("Echoed 'success', flag_submitSuccess: " + flag_submitSuccess);
                        editor.submit(
                            function (success) {
                                console.log("submit(success) was called from within the preSubmit; flag_submitSuccess is: " + flag_submitSuccess);
                                if (flag_submitSuccess === 1) {
                                    flag_submitSuccess = 0;
                                    console.log("Resetting flag_submitSuccess back to: " + flag_submitSuccess);
                                }
                            },
                            null,
                            function (dataCallback) {
                                console.log("dataCallback was called from within the preSubmit; flag_submitSuccess currently is: " + flag_submitSuccess);
                            }
                        );
                    }
                    else {
                        flag_submitSuccess = 0;
                        console.log("Something bad happened, flag_submitSuccess: " + flag_submitSuccess);
                        editor.error('myMainTable.DateStart', 'Some data exists that would conflict with these changes. Please contact the Admin.');
                        editor.error('myMainTable.DateEnd', 'Some data exists that would conflict with these changes. Please contact the Admin.');
                        console.log('The backend script met a condition that would exit execution based on what this Javascript file has transmitted via Ajax POST.');
                        return false;
                    }
                }
            });
        }
        
        if (flag_submitSuccess === 0) {
            console.log("Returning false after all...");
            return false;
        }
    });
    
    ...
    // Inside the TableTools option of the $('#myTable').DataTable variable
    ...
    sRowSelect: "os",
    aButtons: [
        {
            sExtends:        'select_single',
            sButtonClass:    'marginLeft',
            sButtonText:     'Modify Dates',
            fnClick: function () {
                if (thisTable.row('.selected').length !== 0) {
                    editor
                        .title("Modify some dates")
                        .buttons({
                            label: 'Confirm Changes Now',
                            fn: function () {
                                this.submit(
                                    function (success) {
                                        console.log("submit(success) was called from within the button block; flag_submitSuccess is: " + flag_submitSuccess);
                                    },
                                    null,
                                    function (dataCallback) {
                                        console.log("dataCallback was called from within the button block; flag_submitSuccess currently is: " + flag_submitSuccess);
                                    }
                                );
                            }
                        })
                        .edit(thisTable.row('.selected').node());
                }
            }
        }
    ]
    
  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin

    There is always another way to write all code - if it works and you are using the public API (which you are) then that will do nicely!

    Allan

  • jjjetterjjjetter Posts: 3Questions: 1Answers: 0

    Allen,

    I just don't understand what you describe as option 3 above with the flag.

    Is there any way you could just show me the flow of how that would work?

    Something like...

    do preSubmit
    validate some stuff
    if flag is 1
    return true
    do ajax call for additional validation
    on ajax success
    set flag to 1
    editor.submit()
    return false

    Thanks,

    John

  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin
    edited June 2015

    Hi John,

    Something like:

    var flag = false;
    
    editor.on( 'preSubmit', function () {
      if ( flag === false ) {
        // Make Ajax call - on success call editor.submit()
        flag = true;
        $.ajax( ... );
      }
      else {
        // Ajax call has been done - allow to run
        flag = false; // for the next submit
      }
    } );
    

    Allan

This discussion has been closed.