Pierce McGeough
Pierce McGeough

Reputation: 3086

JavaScript call function after form submit complete

I have a hidden form created with a jquery plugin and I need to run a function after the submit has happened but it doesn't appear to be getting called. I need to get the new csrf details after the form has been posted.

After submitting the form I want to get the newly generated csrf details

$(this).on('click', function() {
    $('#' + settings.title.replace(/\s+/g, '-').toLowerCase() + '-export-csv').submit();
    get_csrf_details();
});

Html link with export-csv class and data which will be used in the plugin. Using smarty template.

<a href="#" class="export-csv" data-title='Landlords' data-data='{base64_encode($landlords_json)}'>
    Export (CSV)
</a>

ExportCSV plugin

(function($) {

    $.fn.exportCSV = function ( options ) {

        return $(this).each(function() {
            var settings = $.extend({
                title: null,
                data: null,
                link: '/',
            }, options);

            settings.title = $(this).data('title');
            settings.data = $(this).data('data');

            var hidden_form = "<form id='" + settings.title.replace(/\s+/g, '-').toLowerCase() + "-export-csv' action='" + settings.link + "' method='POST' style='display: none;'>" +
                    "<input type='hidden' class='csrf_field' name='" + csrfName + "' value='" + csrfHash + "'>" +
                    "<input type='hidden' name='title' value='" + settings.title + "'>" +
                    "<input type='hidden' name='data' value='" + settings.data + "'>" +
                "</form>";
            $(this).append(hidden_form);

            $(this).on('click', function() {
                $('#' + settings.title.replace(/\s+/g, '-').toLowerCase() + '-export-csv').submit();
                get_csrf_details();
            });
        });
    }
}(jQuery));

$(".export-csv").exportCSV({
    link: '/dashboard/export-csv'
});

// get the csrf details from server

var get_csrf_details = function get_csrf_details() {
    $.get('/ajax/get-csrf-details', function(response) {
        var csrfName = response.data.csrf.name;
        var csrfHash = response.data.csrf.hash;

        // const csrf_input1 = document.querySelector('.csrf_field');
        const csrf_inputs = document.getElementsByClassName('csrf_field');

        for (i = 0; i < csrf_inputs.length; i++) {
            csrf_inputs[i].name = csrfName;
            csrf_inputs[i].value = csrfHash;
        }
    });
};

Upvotes: 1

Views: 84

Answers (1)

Rory McCrossan
Rory McCrossan

Reputation: 337560

There's no way to know when a submission from a <form> element has been successfully completed.

However, given what you're doing it would make much more sense to just use AJAX. This means you can control the exact logic executed when a response is received and saves having to inject a hidden form and faking a submission, which is far from ideal. Try this:

$.fn.exportCSV = function(options) {
  return $(this).each(function() {
    var settings = $.extend({
      title: null,
      data: null,
      link: '/',
    }, options);

    settings.title = $(this).data('title');
    settings.data = $(this).data('data');

    $(this).on('click', function() {
      var data = {
        title: settings.title,
        data: settings.data
      };
      data[csrfName] = csrfHash;

      $.ajax({
        url: settings.link,
        type: 'POST',
        data: data,
        success: function(response) {
          // the submission has been made, perform required logic here. 
          get_csrf_details();
        },
        error: function() {
          // something went wrong, debug it!
        }
      });
    });
  });
}

A couple of things to note. Firstly, it may make more sense to return the new CSRF in the response of the first request. This will save your network traffic.

Secondly, you're always setting settings.title and settings.data to match the data attributes on the element this function was defined on, so using a settings object is pointless as it will always be overwritten, even if no data attributes are provided. You could instead amend the logic to only use the data if they exist.

Upvotes: 1

Related Questions