Получить несколько соответствующих значений из разных тегов HTML для использования в функции - PullRequest
1 голос
/ 30 марта 2019

Я пытаюсь вызвать функцию, нажав кнопку на боковой панели.

Функция должна найти отмеченные флажки <input> тегов и получить соответствующие имена из <a> тегов .

Затем он передает имена в функцию сценария Google Apps (которая работает) для получения массива календарей из листа.

Затем он собирает массив имен и календарей в один объект {} и передает его другой серверной функции, которая получает события календаря и записывает их на лист (что также работает).

Окончательный результат должен быть: события из календаря записываются на лист (который работает из бэкэнда). Я не получаю события, записанные на листе, когда делаю это с боковой панели.

Так что, я думаю, в этой функции importJobs () есть некоторые ошибки.

    //get button by id, on click run function
    document.getElementById("btn").addEventListener("click", createData)

Функция:

//gets an object with 2 arrays: names and calendars
//to pass to backend function and make records to sheet
function createData() {

     //getting all checkboxes
     var allCheckboxes = document.getElementsByClassName("filled-in")
     
     //getting inputs of start and end dates
     var startdate = document.getElementById("startDate").value
     var enddate = document.getElementById("endDate").value
 
     //getting dates as date objects
     var startDate = new Date(startdate)
     var endDate = new Date(enddate)
    
     var chosenNames = []
     
     //getting all <a> tag elements
     var names = document.getElementsByTagName("a")
     
     //converting elements list into array
     var namesArr = Array.from(names)
     
     //looping all checkboxes
     for (var i = 0; i < allCheckboxes.length; i++) {
     
         //getting value of each checkbox
         var checkbox = allCheckboxes[i].value;
         
         //if checkbox is checked
         if (checkbox == true) {         
           
             //getting correspondent employee name
             var name = namesArr[i].value
             
             //and push it to an array
             chosenNames.push(name)
   
         } else {
         
         continue;             
         }
     };
 
   //object with array of chosen names
   var employees = {
   
     names: chosenNames       
   }

   //getting array of cals calling backend function
   var calendars = google.script.run.loopToGetCals(employees)
   
   //putting aray of cals into object
   employees.cals = calendars
 
    //call backend function to get calendar events
   google.script.run.getCalendarEvents(employees, startDate, endDate)
   
}; 

1 Ответ

1 голос
/ 31 марта 2019

Вероятно, некоторые проблемы с вашим клиентским кодом скрыты в деталях интерфейса связи.Как упоминалось в комментариях, существуют определенные типы данных, которые нельзя передавать между серверной частью скрипта Служб Google и клиентским интерфейсом HtmlService.Особенно примечательны ограничения Date .

Как правило, если я не передаю отдельные значения, я обычно сериализую значение на стороне сервера в JSON перед отправкой его клиенту,Это гарантирует, что передаются только сериализуемые объекты (поэтому не предпринимаются попытки ни к необработанным объектам Date, ни к объектам класса родного скрипта Apps).

Кроме того, я обнаружил, что это делает возврат больших ответов более стабильным: возможно,return <large 2D array> будет иногда рассматриваться как undefined на стороне клиента, в то время как return JSON.stringify(<same 2D array>) будет безопасно доставляться как JSON.parse способный параметр.

Учитывая это, ваше использование синхронного кода должнобыть исправленоПараметр, заданный для withSuccessHandler, должен быть либо функциональной переменной, либо определением встроенной функции, например,

...
 .withSuccessHandler(foo)
...

, где в другом месте пространства имен можно увидеть

function foo(retVal, uObj) { ... }

или

const foo = (retVal, uObj) => { ... }; // or const foo = function (retVal, uObj) { ... };

Встроенный синтаксис будет похож на:

...
  .withSuccessHandler((retVal, uObj) => { ... })
// or
  .withSuccessHandler(function (retVal, uObj) { ... })
...

Во всех этих случаях обработчик успеха вызывается с 2 аргументами - возвращаемое значение серверной функции (arg1),и указанный «пользовательский объект» назначен вызываемому google.script.run исполнителю задач (arg2).

function getCheckedNames() {
  //getting all checkboxes
  const allCheckboxes = Array.from(document.getElementsByClassName("filled-in"));

  //getting all <a> tag elements as a native Array.
  const names = Array.from(document.getElementsByTagName("a"));

  //Reduce from all names to only those that are "checked."
  return allCheckboxes.reduce((arr, cb, i) => {
    // Store the corresponding employee name for any checked checkbox 
    if (cb.value === true)
      arr.push(names[i].value);
    return arr;
  }, []);
}
function requestCheckedCalendars() {
  const chosenNames = getCheckedNames();

  // Submit these names to the backend, to receive their calendar events.
  // Async call, so we will include this object in our call so that the
  // success handler callback can keep working with it.
  google.script.run
    .withUserObject(chosenNames)
    .withSuccessHandler(requestCalendarEvents)
    .loopToGetCals(JSON.stringify({names: chosenNames}));
}
/**
  * @param {string[]} calendars An array of Google Calendar IDs
  * @param {string[]} [chosenNames] An array of names associated with `calendars` (the "user object")
  */
function requestCalendarEvents(calendars, chosenNames) {
  // Convert from JSON-serialized data to native Object types.
  if (typeof calendars === "string")
    calendars = JSON.parse(calendars);
  if (typeof chosenNames === "string")
    chosenNames = JSON.parse(chosenNames);
  if (!chosenNames)
    chosenNames = getCheckedNames();

  const employees = {
    names: chosenNames,
    cals: calendars
  };

  //read inputs of start and end dates
  const startdate = document.getElementById("startDate").value
  const enddate = document.getElementById("endDate").value

  //getting dates as UTC milliseconds
  const startDate = new Date(startdate).getTime();
  const endDate = new Date(enddate).getTime();

  //call backend function to get calendar events
  google.script.run
    // .withSuccessHandler( <some client function> )
    .getCalendarEvents(JSON.stringify(employees), startDate, endDate);
}

Другие ссылки

(теоретически возможно, что вы могли бы использовать Function#bind для предварительной передачи некоторых дополнительных аргументов функции, используемой в качестве обработчика успеха, но я не исследовал это.)

...