1
votes

I'm trying to use HTML5 form validation when using Google Apps Script HTML Service. As another user asked, according to the documentation example, you must use a button input instead of a submit input. Using a submit button seems to do the validation, but the server function is called anyway. The answer given to that user didn't work for me. Also, I want to call two functions when submitting the form and this can make it more complex.

This is what I'm trying to do: The user fills a form and I generate a Google Doc and give him the url. When he clicks the submit button, I show him a jQuery UI dialog saying "Your document is being created" with a nice spinner. Then, when the document is generated, I give him the link. I use the success handler to show the result when the Google Doc stuff is finished, but meanwhile I need a function to show the spinner. I don't know if there is a better way to do that than adding another function to the onclick event and maybe it can be damaging the process in some way. Is there a way not to call any of these functions if the form is not valid (using HTML5 validation)?

This is a simplified version of my code:

Code.gs

function generateDocument(formObject) {
  var doc = DocumentApp.create("Document name");
  ...
  return doc.getUrl();
}

Page.html

<main>
  <form id="myForm">
    ...
    <input type="button" value="Generate document" 
        onclick="showProgress();
            google.script.run
            .withSuccessHandler(openDocument)
            .generateDocument(this.parentNode);"/>
  </form>
  <div id="dialog-confirm" title="Your document">
    <div id="dialog-confirm-text"></div>
  </div>

Javascript.html

$( "#dialog-confirm" ).dialog({ autoOpen: false, resizable: false, modal: true });

function showProgress() {
  $( "#dialog-confirm" ).dialog({ buttons: [ { text: "Cancel", click: function() { $( this ).dialog( "close" ); } } ] });
  $( "#dialog-confirm" ).dialog( "open" );
  $( "#dialog-confirm-text" ).html( "<br />Wait a second, your document is being generated...<br /><br /><img src='http://i.stack.imgur.com/FhHRx.gif' alt='Spinner'></img>" );
  return false;
}

function openDocument(url) {
  $( "#dialog-confirm" ).dialog({ autoOpen: false, resizable: false, width: 400, buttons: [ { text: "Ok", click: function() { $( this ).dialog( "close" ); } } ] });
  $( "#dialog-confirm-text" ).html( '<br /><a href="' + url + '" target="_blank">Click here to open and print your document!</a>' );
  return false;
}

All three HTML docs are joined together (and working with its respective tags) with the include function as recommended in the documentation.

I'm new at jQuery, any advice will be welcome.

A last question: the Cancel button in the dialog will close it but won't stop the doc being created. Is it possible to stop this process? I don't think so.

Thank you very much in advance.

2
Your code is working for me... - rGil
With this code I got an HTML5 validation on the form fields but it didn't stop the server and javascript function getting called, so the validation had no effect on the result and the execution went forward. - nuncaeslupus
It runs because the script function is tied to onclick(). So whenever you click the button, it will run, no matter if the form is validated. The below solution works because the google script is called in a separate function that handles the validation logic. if(formValidated){run google script} - rGil
Then, it would work anyway if you call the function from the button or from the form tag (I mean, while you don't call directly the Google Script function)?. Or the stop after a wrong HTML5 validation would not happen with a button? This is my question to Sandy's answer. - nuncaeslupus
Binding the call to the form object 'onsubmit' will keep the submit from firing if basic html5 validation is taking place, such as a 'required' tag in one of your inputs. But if you are using more complex validation where the logic is in the submit function, then the submit will still be triggered. This is why Sandy puts the call to google script within the validating if() statement. - rGil

2 Answers

0
votes

Move the function call to the <form> element; remove any function call from the submit input element; and put intermediary JavaScript code into a <script> tag:

<input tabindex="9" type="submit" value="Save Input" id='idInputBtn'>


<form id="myInputForm" name="input" onsubmit="fncWriteInput(this)">

<script>
  window.fncWriteInput= function(argTheInfo) {
  // Do additional checks here if you want
  var everythingIsOk = . . . . . . . ;

  if (everythingIsOk) {
    google.script.run
      .withSuccessHandler(openDocument)
      .generateDocument(argTheInfo);
    };
  };

Notice that this.parentNode gets removed to the arg of the function call, and just use this in the function argument because the function is getting called from the <form> element, which is the parent.

If there are any errors, the form will not be submitted, and the user will get a msg that something was wrong. No code will run.

This is pseudo code, but I do use a set up like this in my application. But use developer tools and you can put a break point right in your browser and step through every line to test it without needing to put in console.log statements.

0
votes

I know this has been a long time on this answer, but there's a simple solution that I found:

"<input type='submit' onclick='if(verifyForm(this.parentNode)===true){google.script.run.withSuccessHandler(YOUROUTPUT).YOURFUNCTION(this.parentNode); return false;}' value='Submit'></form>";

Javascript side

 function verifyForm(){
  var elements = document.getElementById("myForm").elements;
  for (var i = 0, element; element = elements[i++];) {
    if (element.hasAttribute("required") && element.value === ""){
      resetInputs();
      return false;
    }
    if (element.hasAttribute("pattern")){
      var value = element.value;
      if(value.match(element.pattern)){
      }else{
        resetInputs();
        return false;
      }
    }
   }
   return true;
}

Calling the window has issues in iOS sometimes, which is why I investigated this further.