这仅适用于您创建小部件的同一执行,而不适用于您检索小部件的后续事件处理程序,因为在这种情况下,无论是否存在,所有内容都是 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 不存在。您可以通过将类型存储在标签中来变得更有趣,但这足以检查小部件是否存在。它之所以有效,是因为根的所有子元素都被添加为回调元素,并且所有回调元素的标签都随处理程序一起发送。请注意,这听起来很昂贵,并且对于具有大量小部件的应用程序来说可能会影响性能,尽管在许多情况下可能没问题,特别是如果您仅将根作为回调元素添加到实际需要验证的处理程序中任意小部件的存在。