google-apps-script - 安全 getElementById 或尝试确定 GUI 中是否存在 ID

标签 google-apps-script

方法UiInstance.getElementById(ID)总是返回 GenericWidget对象,即使 ID 不存在。

有什么方法可以找出我的应用程序中不存在返回的对象,或者检查 UI 是否包含具有给定 ID 的对象?

使用 GUI builder 创建的 UI 的解决方案:

function getSafeElement(app, txtID) {
    var elem = app.getElementById(txtID);
    var bExists = elem != null && Object.keys(elem).length < 100;
    return bExists ? elem : null;
}

如果 ID 不存在,则返回 null。我没有测试所有小部件的键长度边界,所以要小心并用你的 GUI 测试它。

编辑:此解决方案仅适用于 doGet()功能。它在服务器处理程序中不起作用,因此在这种情况下,将它与 @corey-g 答案结合使用。

最佳答案

这只会在您创建小部件的同一执行中起作用,而不是在您检索小部件的后续事件处理程序中起作用,因为在这种情况下,无论是否存在,一切都是 GenericWidget。

您可以亲眼看到解决方案失败:

function doGet() {
  var app = UiApp.createApplication();
  app.add(app.createButton().setId("control").addClickHandler(
      app.createServerHandler("clicked")));
  app.add(app.createLabel(exists(app)));
  return app;
}

function clicked() {
  var app = UiApp.getActiveApplication();
  app.add(app.createLabel(exists(app)));
  return app;
}

function exists(app) {
  var control = app.getElementById("control");
  return control != null && Object.keys(control).length < 100;
}

该应用程序将首先打印“true”,但在单击处理程序上,它将为同一个小部件打印“false”。

这是设计使然; GenericWidget 是一种指向浏览器中小部件的“指针”。我们不会跟踪您创建的小部件,以减少浏览器和脚本之间的数据传输和延迟(否则我们必须发送一长串存在于每个事件处理程序中的小部件列表)。您应该跟踪您创建的内容,并且只“询问”您已经知道存在的小部件(并且您已经知道“真实”类型)。

如果您真的想跟踪存在哪些小部件,您有两个主要选择。第一种方法是在创建小部件时将条目记录到 ScriptDb 中,然后再查找它们。像这样的东西:
function doGet() {
  var app = UiApp.createApplication();
  var db = ScriptDb.getMyDb();
  // You'd need to clear out old entries here... ignoring that for now
  app.add(app.createButton().setId('foo')
      .addClickHandler(app.createServerHandler("clicked")));
  db.save({id: 'foo', type: 'button'});
  app.add(app.createButton().setId('bar'));
  db.save({id: 'bar', type: 'button'});
  return app
}

然后在处理程序中,您可以查找那里的内容:
function clicked() {
  var db = ScriptDb.getMyDb();
  var widgets = db.query({}); // all widgets
  var button = db.query({type: 'button'}); // all buttons
  var foo = db.query({id: 'foo'}); // widget with id foo
}

或者,您可以通过使用标签纯粹在 UiApp 中执行此操作
function doGet() {
  var app = UiApp.createApplication();
  var root = app.createFlowPanel();  // need a root panel
  // tag just needs to exist; value is irrelevant.
  var button1 = app.createButton().setId('button1').setTag(""); 
  var button2 = app.createButton().setId('button2').setTag("");
  // Add root as a callback element to any server handler
  // that needs to know if widgets exist
  button1.addClickHandler(app.createServerHandler("clicked")
      .addCallbackElement(root));
  root.add(button1).add(button2);
  app.add(root);
  return app;
}

function clicked(e) {
  throw "\n" +
      "button1 " + (e.parameter["button1_tag"] === "") + "\n" + 
      "button2 " + (e.parameter["button2_tag"] === "") + "\n" + 
      "button3 " + (e.parameter["button3_tag"] === "");
}

这将抛出:
button1 true
button2 true
button3 false

因为按钮 1 和 2 存在但按钮 3 不存在。您可以通过在标签中存储类型来获得更好的效果,但这足以检查小部件是否存在。它起作用是因为根的所有子元素都被添加为回调元素,并且所有回调元素的标签都与处理程序一起发送。请注意,这听起来很昂贵,对于具有大量小部件的应用程序可能会影响性能,尽管在许多情况下可能没问题,尤其是如果您仅将根作为回调元素添加到实际需要验证任意小部件的存在。

关于google-apps-script - 安全 getElementById 或尝试确定 GUI 中是否存在 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12722806/

相关文章:

google-apps-script - 如何在 Google 应用程序脚本中查找不属于我的文件

google-analytics - 使用 UiService 的 Google Apps 脚本 Web 应用程序可以通过 Google Analytics 进行跟踪吗?

session - Google Scripts Web App 中的 Cookie

google-apps-script - 用于创建 Confluence 页面的 Google Apps 脚本 - 导致状态代码 500

google-apps-script - 在 Google 表格中格式化笔记

javascript - 在 Google Sheet 的新选项卡或窗口中触发网站

javascript - 保护多个范围时,Google Apps 脚本运行时间非常慢

google-apps-script - 检测用户在谷歌电子表格中插入行或列并在脚本中使用react

google-apps-script - 尝试从应用程序脚本获取谷歌分析 4 数据时出现 403 错误

要从 Google 电子表格中捕获的 HTML 选择选项