Prevent Editor from loosing actionable state onComplete?

Prevent Editor from loosing actionable state onComplete?

AlHoldenAlHolden Posts: 5Questions: 1Answers: 0

In a riff on the discussion you had here:
https://datatables.net/forums/discussion/32665/formoptions-oncomplete-none-clears-s-action

Would it be possible to have an additional "onComplete" member of the formOptions family?

>         formOptions: {
>               main: {
>               onComplete: 'wait' // my idea, not a real option
>        }

This option would keep the editor in an open, un-submitted or actionable state (whatever you call it), so that events like "submitSuccess" can be fired over again. The API we're dealing with returns zero or one as a success parameter, so we're trying onComplete: 'none' as a formOption along with

>       editor1.on( 'submitSuccess', function ( e, json, data, action ) {
>           if(json.success==1){
>               toastr.info("Changes submitted.","Success!");
>               editor1.close(); 
>                   }
>           }
>           else{
>               apiNonSuccessHandler(json); // global toastr/logging thing
>                   // and the editor stays open
>           }
>       }

This solution leaves the Editor open if the API returns a fail, but in a state where it cannot be submitted again.

We'll look at the solution presented in the discussion below, but this would mean a considerable rewrite. I was guessing - in my typically novice way - that an option like this in a future release might help more people.
https://datatables.net/forums/discussion/26838/how-do-i-prevent-editor-from-committing-changes-on-ajax-call-during-presubmit
Thanks for reading.

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    Hi,

    Its a neat solution, thanks for suggesting it. But wouldn't:

    editor.on( 'submitComplete', function () {
      editor.edit( table.rows({selected:true}).ids() );
    } );
    

    achieve the same thing? You might need to call create() instead if you want to have it create a new row, or change how rows are selected, but submitComplete could be effectively used as you describe.

    Allan

  • AlHoldenAlHolden Posts: 5Questions: 1Answers: 0

    Thanks, but I've been trying that - with both submitSuccess and submitComplete. The problem with this approach is that all the form values are reset to those of the original row.
    In this scenario, the API has returned a success==0 and we've told the user which value failed validation. Leaving the form as-is (for individual correction) is preferred over forcing them to start all over again.

    editor.on( 'preSubmit', function ( e, json, data, action ) {
            console.log(editor.mode()); // this returns 'edit'
         } );
         
         editor.on( 'submitSuccess', function ( e, json, data, action ) {
            if(json.success==1){
                editor.close();  // the save was good
            }
            else{
                apiNonSuccessHandler(json); // global handler
                console.log(editor.mode()); // this returns null now, so we can't change it?
                editor.edit(dtPatient1.row( { selected: true } )); // works, but all values are reset, we want the submitted data to stay here.
            }
     } );
    

    Tacking your suggested .ids() on the end produces a form where the inputs are filled with the words "Multiple Values"; the same thing happens if I try to edit() with a simple object as the item (array taken from the preSubmit package).

    Thanks again for your answer. I can flesh out the example further if needed.

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    Ah - Are you using server-side processing perhaps? Or something else that I've missed?

    editor.on( 'submitComplete', function () {
      table.one( 'draw', function () {
        editor.edit( table.rows({selected:true}).ids() );
      } );
    } );
    

    should address that.

    Allan

  • AlHoldenAlHolden Posts: 5Questions: 1Answers: 0

    Again, I really appreciate your interest in my problem. Yes, the Editor is making an API call, so a server is processing the contents of the modal form iaw the Editor's ajax object.
    The API returns a 0/1 success bit.
    We do not want the modal to close unless success==1, hence the onComplete: 'none' setting and firing the editor.close() method in the submitSuccess (or submitComplete) handler if this bit is true.
    If the API returns json.success==0, we display the API message (problem for the user to fix) and leave the form open and able to try again.
    But at this point the form is in a "null" mode and won't submit again, the inspiration for my original request.
    Applying the code from your April 11 and April 3 suggestions will erase everything the user had accomplished in the modal form, having refreshed the inputs to their original values from the table row. This would lead to a very frustrating UX if the form had lots of elements which were changed by the user. They would need to re-change everything, possibly failing an entirely different validation with their next submission attempt.

    Here is a complete citation for you (see lines 104 to 120 for the meat):

    <script>
    var patientScheduleArray = [];
    var editor;
    var dtPatient1 = [];
    
    $(document).ready(function() {
        $('.btn-pill-left').removeClass('btn-primary');
        $('.btn-pill-right').addClass('btn-primary');
    
        getpatientScheduleArray();
    
        editor = new $.fn.dataTable.Editor( {
                table: "#patient_list_schedule_table",
                idSrc: 'IDSCHEDULEEVENT',
    
            // THIS IS THE DATA PUTTER
            ajax:  {
                method: "POST",
                url: endpoint + "person.cfm",
                data: function ( d ) {
                    var formData = extractFormAryFromEditor(d);
                    var ownData = {
                        function : 'managePatientScheduleEvents',
                        centerId  : currentCenterId,
                        scheduleEventID : formData.IDSCHEDULEEVENT,
                        startTime       : formData.ontime,
                        durationInMinutes       : formData.Duration,
                        acuityOnPreMinutes  : formData.AcuityOn,
                        acuityOffPreMinutes : '',
                        acuityOnPostMinutes : '',
                        acuityOffPostMinutes    : formData.AcuityOff,
                        note                    : '',
                        chairID             : '',
                        scheduleID          : '',
                        removeOption            : formData.removeOption,
                        userSessionId: currentSessionId,
                        partnerKey  : appKey,
                        laj: 1
                    }
                        return ownData;
                }
            },
    
                fields: [ {
                    name: "IDSCHEDULEEVENT",
                    label: "ID",
                    data: "IDSCHEDULEEVENT",
                    type: "hidden"
                }, {
                    name: "Name",
                    label: "Name:",
                    data: "NAMEFORMATTED",
                    type: "readonly"
                }, {
                    name: "WeekdayName",
                    label: "Weekday:",
                    data: "WEEKDAYNAME",
                    type: "readonly"
                }, {
                    name: "ontime",
                    label: "Ontime:",
                    data: "ONTIME",
                    type: "readonly"
                }, {
                    name: "Duration",
                    label: "Duration:",
                    data: "DURATIONINMINUTES",
                    type: "select",
                    options: selectDurationTime
                }, {
                    name: "AcuityOn",
                    label: "Put-on Acuity:",
                    data: "ACUITYDISPLAY_ON",
                    type: "select",
                    options: selectAcuityMin,
                    def: "15"
                }, {
                    name: "AcuityOff",
                    label: "Take-off Acuity:",
                    data: "ACUITYDISPLAY_OFF",
                    type: "select",
                    options: selectAcuityMin,
                    def: "15"
                }, {
                    name: "removeOption",
                    label: "Remove?:",
                    type: "select",
                    options: [{label:'Do not remove', value:0},{label:'Remove Schedule', value:1},{label:'Create Open Chair', value:2}],
                    def: 0,
                    data: ""
                }
                ],  
            formOptions: {
                main: {
                    onComplete: 'none' // stay open until API returns success==1 
                }
            }
         } );
    
        editor.on( 'preSubmit', function ( e, json, data, action ) {
            console.log(editor.mode()); // fyi - returns 'edit'
        } );
    
        editor.on( 'submitComplete', function ( e, json, data, action ) {
            if(json.success==1){
                if(json.request.REMOVEOPTION != 0){
                    getpatientScheduleArray();
                }
                editor.close();  // the data was saved, so yay.
            }
            else{
                apiNonSuccessHandler(json); // alert user to API error message
                console.log(editor.mode()); // fyi - returns null, so can't resubmit
    // Line below OVERWRITES ALL USER'S CHANGES IN THE FORM 
    // (can we put the SUBMITTED data here instead?)
                editor.edit(dtPatient1.row( { selected: true } )); 
    // Line below fills the form with elements containing the words 'Multiple values'
                // editor.edit(dtPatient1.row( { selected: true } ).ids); 
            }
        } );
    
    });
    
    // THIS IS THE DATA GETTER
    function getpatientScheduleArray() {
        console.info( "getpatientScheduleArray: " + currentCenterId );
        $.post( endpoint + "person.cfm", {
            function: 'getPatientTreatments',
            partnerKey: appKey,
            scheduleEventID: '',
            centerId  :  currentCenterId,
            userSessionId: currentSessionId,
            laj: 1
            },"json" )
    
        .done(function( data ) {
            json = jQuery.parseJSON(data);
            if(json.success=='1'){
                // happy api
                patientScheduleArray = eval(json.data);
    
                ////////////// buttons visible based on privileges: START
                dtButtonArray = [];
                loginAllows = _privDomSettings.patient_list_schedule.dtPatient1;
                // edit btn
                if(loginAllows.indexOf('edit')>-1){
                    dtButtonArray.push(
                        { extend: 'edit',   editor: editor }
                    );
                }
                // print btn
                if(loginAllows.indexOf('print')>-1){
                    dtButtonArray.push(
                        { extend: 'collection',text: 'Print Options', buttons: ['copy',{extend: 'csv', text: 'Excel'},'print'] }
                    );
                }
                ////////////// buttons visible based on privileges: END
    
                dtPatient1 = $('#patient_list_schedule_table').DataTable( {
                    destroy: true,
                retrieve: true,
                    dom: 'BlfrtBip',
                    data: patientScheduleArray,
                    columns: [
                    { title: "Name", data: "NAMEFORMATTED"},
                    { title: "Tx Day", data: {    _: "WEEKDAYSHORTNAME",
                                      sort: "IDWEEKDAY"
                            } },
                    { title: "Shift", data: "SCHEDULESHIFT" },
                    { title: "Pod", data: "PODNAME" },
                    { title: "Chair", data: "CHAIRNAME" },
                    { title: "Ontime", data: "ONTIME" },
                    { title: "Duration", data: "DURATIONINHOURS", render: $.fn.dataTable.render.number( ',', '.', 2) },
                    { title: "Put-on<br />Acuity", data: "ACUITYDISPLAY_ON" },
                    { title: "Take-off<br />Acuity", data: "ACUITYDISPLAY_OFF" }
                ],
                ordering: true,
                order : [[ 0, "asc" ]],
                select: 'single',
                buttons:dtButtonArray,
                lengthMenu: [[15, 30, 60, -1],[15, 30, 60, 'All']],
                } );
    
                dtPatient1.on( 'page.dt', function () {
                    dtPatient1.row( { selected: true } ).deselect();
                } );
             }
             else {
                // unhappy api
                apiNonSuccessHandler(json);
             }
        })
        .fail(function( jqxhr, textStatus, error ) {
            // broken infrastructure
            var err = textStatus + ", " + error;
            console.error( "Request Failed: " + err );
            alert(htmlDecode(err));
        });
    }
    
    function extractFormAryFromEditor(dataObj) {
        var keyNames = Object.keys(dataObj.data);
        var formData = dataObj.data[keyNames];
        return formData;
    }
    </script>
    
    <div id="patient_list_schedules">
        <table id="patient_list_schedule_table" class="display" width="100%"></table>
    </div>
    
  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin
    Answer ✓

    But at this point the form is in a "null" mode and won't submit again, the inspiration for my original request.

    I'm with you now - thank you.

    Use postSubmit to check if the submitted data was good or not - e.g.:

    editor.on('postSubmit', function ( e, json, data, action ) {
      if ( json.success !== 1 ) {
        apiNonSuccessHandler(json);
        json.error = "Error";
      }
    } );
    

    Then remove the onComplete line, and that will allow Editor to just operate as normal (i.e. it will check if there is an error message, if so, the form retains its current state, if not, it will close). Also remove your submitComplete event handler.

    Allan

  • AlHoldenAlHolden Posts: 5Questions: 1Answers: 0

    Ah, so many events. Thanks for pointing me to the right one and it's correct usage.

    No wonder you have earned the double-L version of Allan, while I have only achieved the single-L spelling, to date... ;-]

  • AlHoldenAlHolden Posts: 5Questions: 1Answers: 0

    FYI: Here's the corrected version replacing lines 104-120 above, as employed in our app.
    (also, the formOptions clause has been removed)

    editor.on('postSubmit', function ( e, json, data, action ) {
        if(json.success==1){
            if(json.request.REMOVEOPTION != 0){
                getpatientScheduleArray();
            }
        }
        else {
            apiNonSuccessHandler(json);
            json.error = "Error";   // this is key to keeping the modal open
        }
    } );
    
This discussion has been closed.