Home > Blockchain >  Update scriptlets in HTML without reloading page
Update scriptlets in HTML without reloading page

Time:09-24

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>

CodePudding user response:

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')
}
  • Related