1

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;
 }
 });
};
asked Oct 18, 2018 at 13:03
3
  • 2
    There's no way to know when a submission from a <form> element has been successfully completed. 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 injecting a form and faking a submission, Commented Oct 18, 2018 at 13:06
  • @RoryMcCrossan True, good shout. I threw in a timeout but need to be sure on the time finishing. Commented Oct 18, 2018 at 13:13
  • 1
    A timeout is far from ideal too, as it will either mean that the user is waiting longer than required after the request completes, or if the request takes too long the timeout will execute before the page is ready and the logic will break completely. I added an answer for you below which shows how to do this in AJAX. Commented Oct 18, 2018 at 13:15

1 Answer 1

1

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.

answered Oct 18, 2018 at 13:14
Sign up to request clarification or add additional context in comments.

2 Comments

It will eventually get moved to a method call but not today :(
This now isnt doing the download like it did previously with the form submit. Its going to PHP server code and debugging seems to show everything works as before. All except the download of the csv file. Do i need to catch the response now or something?

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.