0

I am referring to this article about templated HTML and scriptlets with Google Apps Script: https://developers.google.com/apps-script/guides/html/templates

It is written how to call an Apps Script function and load the data when loading the html page:

Code.gs:

function doGet() {
  return HtmlService
      .createTemplateFromFile('Index')
      .evaluate();
}

function getData() {
  return SpreadsheetApp
      .openById('1234567890abcdefghijklmnopqrstuvwxyz')
      .getActiveSheet()
      .getDataRange()
      .getValues();
}
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <? var data = getData(); ?>
    <table>
      <? for (var i = 0; i < data.length; i++) { ?>
        <tr>
          <? for (var j = 0; j < data[i].length; j++) { ?>
            <td><?= data[i][j] ?></td>
          <? } ?>
        </tr>
      <? } ?>
    </table>
  </body>
</html>

Question: Is it possible to update the scriptlets without refreshing the whole page? For example to implement a button and call the getData() function to load new data from the spreadsheet to the html?

Update:

I have adjusted the code with a simple button and a code to call the getData() function again and update the table. But of course doing it this way the for loop gets lost. Better would be to reload the whole code. Is there a way to re-evaluate the whole page? Any ideas?

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <button type="button" onclick="Refresh()">Refresh</button>
    <? var data = getData(); ?>
    <table id="datatable">
      <? for (var i = 0; i < data.length; i++) { ?>
        <tr>
          <? for (var j = 0; j < data[i].length; j++) { ?>
            <td><?= data[i][j] ?></td>
          <? } ?>
        </tr>
      <? } ?>
    </table>
  </body>

<script>

  function Refresh(){
    google.script.run.withSuccessHandler(update).withUserObject(this).getData();
  }      
            
  function update(returnValue){
    document.getElementById("datatable").innerHTML= returnValue
  }

</script>

</html>
5
  • google.script.run Commented Sep 21, 2022 at 18:43
  • 2
    Documentation Say:Remember, however, that because template code executes before the page is served to the user, these techniques can only feed initial content to a page. To access Apps Script data from a page interactively, use the google.script.run API instead. Commented Sep 21, 2022 at 19:27
  • Yes, I have read that and know how to call the getData() function. But I dont know how to update the scriptlet or to re-evaluate the html. Any ideas? Commented Sep 21, 2022 at 19:35
  • How do you want that the DOM be updated? Do you want to use a button for that? How do you will include the required JavaScript for the client-side? Please edit the question to add more details including a brief description of your search efforts for helpful answers from this site as is suggested in How to Ask. Commented Sep 21, 2022 at 20:09
  • 1
    I have made an upate of my question with the button and the current issue Commented Sep 22, 2022 at 7:53

1 Answer 1

0

If you will call getData() from the client-side, then you will need to build the table on the client-side. The easier way might be to create a string and then add it by using HtmlElement.outerHTML to replace the whole element or HtmlElement.innerHTML to replace the inner elements and content.

Client-side JavaScript code (put it between <script> tags, do not require to change your server-side code)

function refreshTable(){
  google.script.run
    .withSuccessHandler(updateTable)
    .withFailureHandler((error) => console.error(error.message))
    .getData()

}

function updateTable(data){
  let html = '';
  for (var i = 0; i < data.length; i++) {
    html += `<tr>`;
      for (var j = 0; j < data[i].length; j++) {
        html += `<td>${data[i][j]}</td>`;
      } 
    html += `</tr>`;
  }
  document.getElementById("datatable").innerHTML = html;
}

By the other hand, if you want to use Google Apps Script templated HTML to build the HTML table, then you need to call a function that evaluates the template to generate a HttpOutput object and then use HttpOutput.getContent() to return a string to the client side code, then you might pass this string to the corresponding element by using HtmlElement.innerHTML.

Server Side, in a .gs file

function includeFromTemplate(filename){
  return HtmlService.createTemplateFromFile(filename).evaluate().getContent();
}
Server side, table.html file
<? var data = getData(); ?>
<? for (var i = 0; i < data.length; i++) { ?>
  <tr>
    <? for (var j = 0; j < data[i].length; j++) { ?>
      <td><?= data[i][j] ?></td>
    <? } ?>
  </tr>
<? } ?>

Client Side. Call this function from onclick attribute or use the HtmlElement.addEventlistener method.

function refreshTable(){
  google.script.run
  .withSuccessHandler(html => {
    document.querySelector('table').innerHTML = html;
  })
  .withFailureHandler((error) => console.error(error.message))
  .includeFromTemplate('table')
}
Sign up to request clarification or add additional context in comments.

Comments

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.