Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update ajax to use fetch API #131

Closed
mckennapsean opened this issue Jul 19, 2017 · 6 comments
Closed

update ajax to use fetch API #131

mckennapsean opened this issue Jul 19, 2017 · 6 comments

Comments

@mckennapsean
Copy link
Collaborator

This API change for sending the form data may be more robust and result in more clear code for people following along the tutorial.

The fetch API is supported by all evergreen browsers. We could have polyfill support for IE.https://github.com/github/fetch

@mckennapsean
Copy link
Collaborator Author

Considering AJAX has limited support on IE 10/11 anyways, this may be worth the cleaner code http://caniuse.com/#search=fetch

@RDhar
Copy link
Member

RDhar commented Apr 1, 2018

Given that we can leverage Fetch API to submit the form data from the front-end, I think this would be an excellent enhancement to implement.

Just for reference, this is how I've adapted your code to integrate Fetch API in an isolated, simplified format using ES5 Javascript.

form.addEventListener('submit', function (e) {
  e.preventDefault();
  var formName = document.getElementsByName('name')[0].value;
  fetch(scriptURL, {
    body: new FormData(form),
    method: 'POST',
  })
  .then(function (response) {
    form.innerHTML =
      'Thanks for your message, ' + formName + '.';
    return console.log('Success!', response);
  })
  .catch(function (error) {
    return console.error('Error!', error.message);
  });
});

As per your FAQs section, here's a working demo of the entire code hosted on CodePen.

See the Pen Contact Form Demo by Rishav Dhar (@rdhar) on CodePen.

I believe this considerably improves legibility of the existing code, as shown in the snippet below, and further lowers the barrier to understanding the phenomenal work you've done so far. Thanks for your time and patience!

function handleFormSubmit(event) { // handles form submit withtout any jquery
event.preventDefault(); // we are submitting via xhr below
var data = getFormData(); // get the values submitted in the form
/* OPTION: Remove this comment to enable SPAM prevention, see README.md
if (validateHuman(data.honeypot)) { //if form is filled, form will not be submitted
return false;
}
*/
if( !validEmail(data.email) ) { // if email is not valid show error
document.getElementById("email-invalid").style.display = "block";
return false;
} else {
var url = event.target.action; //
var xhr = new XMLHttpRequest();
xhr.open('POST', url);
// xhr.withCredentials = true;
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
console.log( xhr.status, xhr.statusText )
console.log(xhr.responseText);
document.getElementById("gform").style.display = "none"; // hide form
document.getElementById("thankyou_message").style.display = "block";
return;
};
// url encode form data for sending as post data
var encoded = Object.keys(data).map(function(k) {
return encodeURIComponent(k) + "=" + encodeURIComponent(data[k])
}).join('&')
xhr.send(encoded);
}
}

@mckennapsean
Copy link
Collaborator Author

thanks for sharing, @RDhar ! very cool. did you want to open a PR with the fetch API instead of XHR? I think we are looking to keep the other enhancements the form has, but your proof of concept is very simple which I like 👍

@RDhar
Copy link
Member

RDhar commented Apr 2, 2018

Thanks, @mckennapsean. Since this is a pretty major overhaul of how data is communicated from the form, I'm not sure I can provide a reliable PR for it all in one go just yet!

Furthermore, I made an attempt at it but I couldn't get any form data to populate your spreadsheet using your web app URL. This suggests some modifications are due on your Google Sheets Script itself to make it compatible with changes brought about by Fetch API.

More specifically, I think you have to introduce a ContentService to parse the JSON into spreadsheet rows while taking the MimeType into account. An example of this is shown below.

return ContentService
  .createTextOutput(JSON.stringify({
    result: 'success',
    row: nextRow,
  }))
  .setMimeType(ContentService.MimeType.JSON);

For a more complete example, feel free to go through my copy of the spreadsheet (be warned, it's heavily commented!) that's connected to my CodePen demo above. You should have full access to the Script Editor as I've shared it publicly. The email address it contains is a temporary placeholder so no worries there.

If you have further thoughts on this, particularly the "server-side" data handling by Google Sheets Script, I'd be really grateful to hear them on #220 to address the functionality of sending emails. Thanks!

@mckennapsean
Copy link
Collaborator Author

no worries, I think the fetch part of it can be abstracted out and just replace what we have in the XHR part. I can do this otherwise, no sweat. I left a comment on the other issue on what may be going on.

@mckennapsean
Copy link
Collaborator Author

While digging further into this issue, it would require Promise polyfill support on top of Fetch polyfill support, and this slowly gets more and more complex, beyond that for a standard tutorial.

Keeping cross-browser support is too critical, otherwise people's forms won't work, and they/their clients will be sad. For those tech-savvy enough, switching to Fetch wouldn't be hard anyways. It is a good exercise, and it would make a good "Advanced example" should anyone be interested. For now I'll close with some tags in case we have time and revisit this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants