P Burke
P Burke

Reputation: 1772

Control Flow Between Server and Client and Back to Server for Google Apps Script

I have a question about the control flow between some JavaScript code running as bound functions within a google spreadsheet - so server side - and a dialog (that happens to be Modal, but Modeless is the same) that is client side.

While the code examples below work fine in that the dialog successfully calls the server side function as per the line below, and the withSuccessHandler works too.

google.script.run.withSuccessHandler(success_callback).getCredentials(this.parentNode)

But what I actually want to achieve is for some server side code to carry on executing once the dialog has gone; ideally from the point the .showModalDialog() function was called, but I'd be happy just passing control back to any server-side function.

Some example software is below; don't forget this works, just not how I want it too! Essentially the event handler for a menu item created by the the OnOpen() function calls a modal dialog to prompt the user for security credentials.

var html = HtmlService.createHtmlOutputFromFile('authorization_dialog');
      SpreadsheetApp.getUi() 
          .showModalDialog(html, 'Authorization Dialog');

The HTML file:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>

  <body>
    <form>    
        Authorization Code:&nbsp;&nbsp;
        <input type="text" name="authorization_code"><br><br>
        Account ID:&nbsp;&nbsp;
        <input type="text" name="account_id"><br><br>
        Enter account details...
        <br>
        <br><br>
        <input type="button" value="OK"
             onclick="google.script.run.withSuccessHandler(success_callback).getCredentials(this.parentNode)" />    
        <input type="button" value="Close"
             onclick="google.script.host.close()" />

    </form>

    <script>

       // Using this call back prevents the need to hit the Close Button after OK.
       function success_callback() {
         google.script.host.close(); // Close the dialog.
       }
    </script>
  </body>
</html>

Upvotes: 0

Views: 498

Answers (1)

Anton Dementiev
Anton Dementiev

Reputation: 5716

If you don't need a response from the server-side function, simply omit 'withSuccessHandler';

function func_client(){

google.script.run.func_server();
google.script.host.close();


}

In this case, the server-side code will continue executing without locking your client's UI - you can call any other functions inside 'func_server'.

If you'd like to process a response from the first function call, call the second function from 'success_callback'. The dialog will be closed without waiting for the google.script.run to complete, but the server code will continue executing. In the example below, the 1st server function passes form data back to the client where 'success_callback' immediately invokes another server function that takes a while to complete (it logs each file in my Google Drive);

Client:

 <form id="form">
    .....
        <input type="submit" id="ok" value="OK" />    
        <input type="button" value="Close" onclick="google.script.host.close()" />    
    .....
   </form>

<script>
   window.onload = function(){

    document.getElementById("form")
            .addEventListener("submit", function(e){

    e.preventDefault();

    google.script.run
                 .withSuccessHandler(success_callback)
                 .logFormData(this);

});


}

   function success_callback(response) {

     console.log(response);

     google.script.run.scanFiles();
     google.script.host.close(); // Close the dialog.
   }
</script>  

Server:

function showDialog(){

var ui = SpreadsheetApp.getUi();

//IMPORTANT: client-side scripts won't be executed 
//without calling evaluate() on the HtmlTemplate object before passing it to UI;

var template = HtmlService.createTemplateFromFile("dialog");
var html = template.evaluate();

ui.showModalDialog(html, "dialog");


}


function logFormData(formData){


return formData;

}


function scanFiles() {

var files = DriveApp.getFiles();
var file;  

  while (files.hasNext()) {

  file = files.next();

    Logger.log(file.getName() + ": " + file.getMimeType());


  }


}

Upvotes: 0

Related Questions