【问题标题】:Calling server function onclick and returning templated html调用服务器函数 onclick 并返回模板化 html
【发布时间】:2016-07-12 11:42:48
【问题描述】:

每次我在createArtistList() 函数中单击var buttonTemplate 中的“+”按钮时,我都会尝试从code.gs 文件中调用getArtistName() 函数。

它现在做的是:

  • var buttonTemplate = '<li><a onClick="addArtist(); return false;" href="">buttonCell</a></li>'; 在 Web 应用上被点击时,它会运行 js.html 文件中的 addArtist() 函数
  • 然后调用 code.gs 文件中的 writeArtistName() 函数,并将输入到提示中的值写入电子表格。

我还需要它来调用 code.gs 文件中的 getArtistName() 函数,以便我可以使用刚刚输入电子表格的值更新网络应用程序。

 

谷歌应用脚​​本支持实时更新吗?

有没有办法同时从 google.script.run 调用 2 个函数?

例子:

google.script.run
      .withSuccessHandler(writeSuccess(artistName))
      .withFailureHandler(writeFailure)
      .writeArtistName(artistName);

添加类似这样的内容 - .writeArtistName(artistName), .getArtistName();?

 


 

index.html:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <?!= getContent("js") ?>
    <?!= getContent("css") ?>
    <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Abel">
  </head>
  <body>
    <!-- //nav tabs// -->
    <div id="artistTabs">
      <ul id="artistList">
        <?!= createArtistList(); ?>
      </ul>
    </div>
  </body>
</html>

 

js.html:

<script>
function addArtist()
{
  var artistName = prompt("enter artist whole first name and initial of last name");

  if (artistName === "") //user pressed 'ok' but input field was empty
  {
    return;
  }
  else if (artistName != "" && artistName !== null) //user inputs something and hits 'ok'
  {
    google.script.run
      .withSuccessHandler(writeSuccess(artistName))
      .withFailureHandler(writeFailure)
      .writeArtistName(artistName);
  }
  else //user hits 'cancel' or 'x'
  {
    return;
  }
}

function writeSuccess(artistName)
{
  console.log("write success: " + artistName);
}

function writeFailure()
{
  console.log("write failure - email myself why it failed and the time it failed");
}

function test()
{
  console.log("test"); //open this artists spreadsheet
}
</script>

 

code.gs:

var ss = SpreadsheetApp.openById('id');
var sheet = ss.getSheets()[0];

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

function getContent(filename)
{
  return HtmlService.createHtmlOutputFromFile(filename).getContent();
}

function createArtistList()
{
  //button
  var buttonStartingRow = 2;
  var buttonStartingColumn = 1;

  var buttonCell = sheet.getRange(buttonStartingRow, buttonStartingColumn).getValue();

  var x = '<li><a onClick="addArtist(); return false; return getArtistName();" href="">';
  var y = buttonCell;
  var z = '</a></li>';

  var buttonTemplate = x + y + z;

  //artist names
  var artistsOutput = '';

  var startingRow = 2;
  var startingColumn = 1;
  var howManyRows = sheet.getLastRow() - 1;
  var howManyColumns = 1;

  var allArtistsArray = sheet.getRange(startingRow, startingColumn, howManyRows, howManyColumns).getValues(); //get every name in 1st column after second row

  for (i = 0; i < allArtistsArray.length; i++)
  {
    allArtistsArray = allArtistsArray.filter(function(n){return n[0] !== '' && n[0] !== buttonCell}); //filter 'buttonCell' value and blank rows
    allArtistsArray = allArtistsArray.toString().split(","); //flatten 2d array to 1d array

    if (allArtistsArray == '')
    {
      Logger.log("array = blank");
      return buttonTemplate;
      break; //leave loop and only return 'buttonTemplate'
    }
    else
    {
      var x1 = '<li><a onClick="test(); return false;" href="">';
      var z1 = '</a></li>';

      var _1 = allArtistsArray[i];
      var _2 = x1 + _1 + z1;

      artistsOutput += _2
    }
  }
  return buttonTemplate + artistsOutput; //return 'buttonTemplate' and every value from spreadsheet that is not blank
}

function writeArtistName(artistName)
{
  var lastRow = sheet.getLastRow() + 1; //gets next unused row
  var column = 1; //first column
  var lastCell = sheet.getRange(lastRow, column);

  lastCell.setValue(artistName); //sets next blank row as artistName
}

function getArtistName()
{
  var lastRow = sheet.getLastRow(); //gets last row with content
  var column = 1;

  var lastArtist = sheet.getRange(lastRow, column).getValue(); //gets last row with artistName

  //Logger.log(lastArtist);

  var x = '<li><a onClick="test(); return false;" href="#">';
  var y = lastArtist;
  var z = '</a></li>';

  var xyz = x + y + z;

  Logger.log(xyz);

  return xyz;
}

//figure out how to call getArtistName() from buttonTemplate onClick
//and have the artist name from last row return and display in the list

【问题讨论】:

  • 您可以对google.script.run.func() 进行多次后续调用。google.script.run 客户端 API 在客户端中运行下一行代码之前不会停止等待回调。您不能将第二个函数调用链接到一个 google.script.run 实例,但您可以简单地在第一个调用之后立即进行第二个完整调用。无法保证服务器函数完成回调的顺序。第二个google.script.run 可以先完成。所以如果第二个withSuccessHandler()依赖第一个完成,就会有问题。
  • Google 服务器上的 JavaScript 函数将同时运行。它与浏览器中运行的 JavaScript 不同。
  • 这一行:withSuccessHandler(writeSuccess(artistName)) 有错误。它必须是:withSuccessHandler(writeSuccess) 服务器的返回值会自动发送到成功处理函数括号中的参数。您所需要的只是服务器函数中没有的 return 语句,以及成功函数括号中的参数,而您有。
  • 我应该从 writeArtistName() 函数返回 getArtistName() 函数内容吗?会在网络应用程序上显示它吗?

标签: javascript google-apps-script


【解决方案1】:

你有一个很好的理由不能让一个服务器功能同时兼顾两者吗?

比如:

function writeAndGetArtistName(artistName)
{
  writeArtistName(artistName);
  return getArtistName();
}

那么你的客户端代码只会调用这个函数。

尽管如果我理解您在这里尝试做什么,并且您的 getArtistName 函数只是获得与 writeArtistName 刚刚添加到电子表格中的相同的艺术家名称,那么将艺术家名称传递给 getArtistName 可能会更容易,然后您会得到跳过这三行代码:

  var lastRow = sheet.getLastRow(); //gets last row with content
  var column = 1;

  var lastArtist = sheet.getRange(lastRow, column).getValue(); //gets last row with artistName

【讨论】:

  • 既然你提到了它,我可以把它放在一个函数中。但问题来自于尝试在单击按钮时将输入电子表格的值显示到 Web 应用程序。我真的不知道该怎么做。由于 scriptlet,我有显示按钮,但我不认为我可以从 onclick 函数制作另一个 scriptlet,然后显示 getArtistName() 函数。
  • 我认为根据功能分离它们正在做的事情很好。对于您的另一个问题,我相信 Sandy Good 的评论有正确的答案:您的成功处理程序应该看起来像这样:withSuccessHandler(writeSuccess) 并且您正在调用的脚本应该返回您的成功处理程序的第一个参数。
  • 我更改了withSuccessHandler 并返回了艺术家姓名,但我需要将其作为列表项附加到无序列表中。我试图弄清楚如何让它从服务器显示,我猜是模板化的 html。像 &lt;?!= createArtistList ?&gt; 一样,我需要它留在网络应用程序上,并且任何人都可以从任何地方访问,而不是作为本地存储。
  • 将它作为字符串返回并将您的服务器变量连接到其中可能是最简单的,这样您就可以返回类似"&lt;li&gt;" + text + "&lt;/li&gt;" 的内容。如果您想从文件中返回整个模板,您可以执行template = HtmlService.createTemplateFromFile('yourFile'); 之类的操作,然后返回template.evaluate()。然后在您的客户端中,您可以将其附加到列表的末尾,例如$('#yourList').append(serverLi);
猜你喜欢
  • 1970-01-01
  • 2017-11-16
  • 1970-01-01
  • 2010-12-19
  • 1970-01-01
  • 2011-10-07
  • 1970-01-01
  • 1970-01-01
  • 2021-11-10
相关资源
最近更新 更多