Не удается обновить метку в интерфейсе GUI Builder скриптов Google Apps во время выполнения

У меня есть интерфейс, который вызывает сценарий для создания электронной таблицы с использованием данных, взятых из другой электронной таблицы. Я хочу, чтобы интерфейс обновлял свои метки во время выполнения, чтобы дать пользователю визуальную обратную связь и сообщить ему, что скрипт работает и не зависает. Когда я пытаюсь обновить метку, которую я поместил в интерфейс, она не обновляется в первый раз, но обновляется правильно после того, как myFunction() достигает своего конца. Это означает, что я вижу сообщение "Создание завершено", но сообщение "Создание файла..." никогда не отображается. Кроме того, кнопка buttonCompile никогда не отключается, поэтому кажется, что инструкции перед myFunction() вообще не выполняются. Как я могу обновить метки и отключить кнопку до того, как myFunction() начнет выполняться? (я уже перепроверил ссылки на переменные)

function doGet() {
  var app = UiApp.createApplication();
  app.add(app.loadComponent("File creation"));
  var buttonCreate = app.getElementById('createBtn');
  var handlerCrea = app.createServerHandler('createClickHandler');
  buttonCreate.addClickHandler(handlerCreate);
  return app;
}

function createClickHandler(e) {
  var app = UiApp.getActiveApplication();
  var label = app.getElementById('createLbl');
  label.setText("Creating file...");
  var buttonCompile = app.getElementById('compileBtn');
  buttonCompile.setEnabled(false);
  myFunction();
  label.setText("Creation completed.");
  buttonCompile.setEnabled(true);
  app.close();
  return app;
}

person m.piras    schedule 08.10.2012    source источник


Ответы (1)


Причина такого поведения в том, что графический интерфейс обновляется только после выхода из обработчика. Обходной путь — использовать два обработчика. 1-й устанавливает текст метки на Creating file... и отключает кнопку, 2-й выполняет функцию myFunction, меняет текст на Creation completed, и активирует кнопку. Вот пример. Он отключает/включает кнопку, а рабочий обработчик просто ждет 5 секунд.

function doGet(e) {
  var app = UiApp.createApplication();
  var container = app.createHorizontalPanel().setId('container');
  var btnPerformance = app.createButton("Performance Demo").setId('btnPerformance');
  var handlerPerformance = app.createServerHandler('onBtnPerformanceClick');
  var handlerWait = app.createServerHandler('onWait');
  btnPerformance.addClickHandler(handlerPerformance);
  btnPerformance.addClickHandler(handlerWait);
  container.add(btnPerformance);
  app.add(container);
  return app;
}

function enableControls(enable) {
  var lstControls = [ 'btnPerformance' ];
  var app = UiApp.getActiveApplication();
  for (var i = 0; i < lstControls.length; i++) {
    var ctl = app.getElementById(lstControls[i]);
    ctl.setEnabled(enable);
  }
}

function onWait(e) {
  enableControls(false);
  return UiApp.getActiveApplication();
}

function onBtnPerformanceClick(e) {
  Utilities.sleep(5000);
  enableControls(true);
  return UiApp.getActiveApplication();
}
person megabyte1024    schedule 08.10.2012
comment
Просто из любопытства, задокументировано ли это поведение где-нибудь в документе Apps Script? Ничего не нашел по этому поводу, может что-то пропустил - person m.piras; 08.10.2012
comment
@ m.piras, я не знаю, либо это где-то задокументировано. Насколько я помню, я нашел это решение на этом сайте. - person megabyte1024; 08.10.2012