1

I have a Google Apps Script Webapp which serves a simple html form. My Apps Script function processData(formdata) receives the form data as a Blob as described here . After I process the data I want to return another simple html page to the user. I tried the naive approach like this:

function processData(formdata){
  // do something with the data
  process(formdata);
    return HtmlService
    .createHtmlOutputFromFile('html/final')
   }

However the page is always blank after the user submits the data. How can I give the user a proper response?

This is my second approach as suggested by @Cooper. I added it in the html and used the withSuccessHandler but the page remains white after submitting:

<!DOCTYPE html>
<html>
 <head>
<link
  rel="stylesheet"
  href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"
/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script>
function updateUrl() {
var div = document.getElementById('msg');
div.innerHTML = "<h1>Thanks for the submission</h1><p>You should be hearing from us soon</p>";
}
function handleFormSubmit(formObject) {
  google.script.run.withSuccessHandler(updateUrl).processForm(formObject);
    }
</script>
</head>

<body>
<div id="msg"></div>
<div class="container">
  <h1>FORM insert data</h1>
  <form id="myForm" onsubmit="handleFormSubmit(this)">
    <div class="form-group">
      <label for="nameInput">enter your name</label><br />

... and so on

[Edit]

I now added the preventFormSubmit function as described in the example by Cooper. Now after submitting the message is shown. However the complete form stays on the page where I would prefere to only have the message be shown.

That said it seems that it is not easy to just show another html. Does that mean it is not possible to have a more complex webapp which require more html sides with Google Apps Script?

20
  • I would probably do it on the same page with another div and use google.script.run to connect to the server if necessary. Commented Jun 29, 2020 at 17:21
  • how will this look like? I dont have any experience with html Commented Jun 29, 2020 at 17:24
  • What do want it look like? Commented Jun 29, 2020 at 17:25
  • You can try some site like JS Fiddle to play around with different options if you want. Commented Jun 29, 2020 at 17:26
  • Perhaps you put something like this in the html <div id="msg"></div> along with <style> #msg{display:none;}</style> and then with Javascript to load message into the div with document.getElementById('msg').innerHTML="<h1>Thanks for the submission</h1><p>You should be hearing from us soon</p>" and then you can change the style with $('#msg').css('display','block'); of course you'll have to include JQuery on your page as well. Fortunate Google host all of those types of things for people to use. But you can also do it with straight javascript. Commented Jun 29, 2020 at 17:31

1 Answer 1

2

You were right there were some problems with that example that are a result of the recent switch to the v8 engine. I didn't use the doGet(), I ran it as a dialog instead. But here's a working version.

Code.gs:

function runADialog() {
  SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutputFromFile('ah1'), 'MCVE')
}

function processForm(data) {
  SpreadsheetApp.getActive().toast('processForm');
  console.log('processForm');
  var file = Utilities.newBlob(data.bytes,data.mimeType,data.name)
  var driveFile = DriveApp.createFile(file);
  return driveFile.getUrl();
}

ah1.html:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function preventFormSubmit() {
        var forms=document.querySelectorAll('form');
        for (var i=0;i<forms.length;i++) {
          forms[i].addEventListener('submit', function(event) {
            event.preventDefault();
          });
        }
      }
      window.addEventListener('load', preventFormSubmit);
      
      function handleFormSubmit(formObject) {
        console.log('handleFormSubmit');
        const file = formObject.myFile.files[0];
        console.log(file);
        const fr = new FileReader();
        fr.onload = function(e) {
          const obj = {name:file.name,mimeType: file.type,bytes:[...new Int8Array(e.target.result)]};
          google.script.run.withSuccessHandler(updateUrl).processForm(obj);
        }
        fr.readAsArrayBuffer(file);
      }
      
      function updateUrl(url) {
        var div = document.getElementById('output');
        div.innerHTML = '<a href="' + url + '">Got it!</a>';
      }
    </script>
  </head>
  <body>
    <form id="myForm" onsubmit="handleFormSubmit(this)">
      <input name="myFile" type="file" />
      <input type="submit" value="Submit" />
    </form>
    <div id="output"></div>
 </body>
</html>

Most of the modifications for this example came from Tanaike

This is what the dialog looks like when it works:

enter image description here

and you can click on that link to go to the file.

And this is a version using that other div I was talking about.

Code.gs:

function runADialog() {

SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutputFromFile('ah1'), 'MCVE')
}

function processForm(data) {
  SpreadsheetApp.getActive().toast('processForm');
  console.log('processForm');
  var file = Utilities.newBlob(data.bytes,data.mimeType,data.name)
  var driveFile = DriveApp.createFile(file);
  return driveFile.getUrl();
}

function getServerInfo() {
  //getting nothing for now
  return{msg:"This is the default message."};
}

ah1.html:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <script>
      function preventFormSubmit() {
        var forms=document.querySelectorAll('form');
        for (var i=0;i<forms.length;i++) {
          forms[i].addEventListener('submit', function(event) {
            event.preventDefault();
          });
        }
      }
      window.addEventListener('load', preventFormSubmit);
      
      function handleFormSubmit(formObject) {
        console.log('handleFormSubmit');
        const file = formObject.myFile.files[0];
        console.log(file);
        const fr = new FileReader();
        fr.onload = function(e) {
          const obj = {name:file.name,mimeType: file.type,bytes:[...new Int8Array(e.target.result)]};
          google.script.run
          .withSuccessHandler(function(url){ 
             updateUrl(url);
             google.script.run
             .withSuccessHandler(function(obj){
               document.getElementById("msg").innerHTML="<h1> Thanks for Submitting that Image<h1><p>" + obj.msg + "</p>";
               
             })
             .getServerInfo();
           })
          .processForm(obj);
        }
        fr.readAsArrayBuffer(file);
      }
      
      function updateUrl(url) {
        var div = document.getElementById('output');
        div.innerHTML = '<a href="' + url + '">Got it!</a>';
      }
    </script>
  </head>
  
  <body>
    <form id="myForm" onsubmit="handleFormSubmit(this)">
      <input name="myFile" type="file" />
      <input type="submit" value="Submit" />
    </form>
    <div id="output"></div>
    <div id="msg"></div>
 </body>
</html>

And this is what the new dialog looks like:

enter image description here

Sign up to request clarification or add additional context in comments.

3 Comments

this is interesting, when I test it similar to your example it works, so the question is why doesnt it in my version
I did change the way the file is read when you upload it if you’ll notice there’s a file reader in there
I am a bit confused when you said that you do not use a doGet() method. But afaik you need one right? And where does the runADialoge() gets called?

Your Answer

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.