Get multiple corresponding values from different HTML tags to use in a function

一世执手 提交于 2020-01-16 03:27:05

问题


I am trying to call a funtion by pressing the button on my sidebar.

The function should find checked checkboxes of <input> tags and get corresponding names from <a> tags.

Then it passes names to backend Google Apps script function (which works) to get an array of calendars from sheet.

Then it collects an array of names and calendars into one object{} and passes it to another backend function which gets calendar events and writes them to a sheet (which also works).

The final result should be: events from calendar written to a sheet (which works from backend). I don't get the events written on a sheet when do it from a sidebar.

So I guess there are some errors in this importJobs() function.

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

The function:

//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:


Probably some of the issues with your client-side code are hidden in the details of the communication interface. As mentioned in comments, there are certain datatypes that cannot be passed between the Google Apps Script backend, and the HtmlService client-side frontend. Particularly notable are the Date restrictions.

As a general rule, unless I am passing single values, I will usually serialize a server-side value to JSON before sending it to the client. This makes certain that only serializable things are being transmitted (so no raw Date objects are attempted, nor native Apps Script class objects).

Additionally, I have found that this makes returning large responses more stable: perhaps a return <large 2D array> will occasionally be seen as undefined in the client side, while return JSON.stringify(<same 2D array>) will arrive safely as a JSON.parseable parameter.

With that in mind, your use of synchronous code needs to be amended. The parameter given to withSuccessHandler should be either a function variable or an inline function definition, e.g.

...
 .withSuccessHandler(foo)
...

where elsewhere in the namespace one sees

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

or

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

Inline syntax would be similar to:

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

In all these cases, the success handler is invoked with 2 arguments - the return value of the server-side function (arg1), and the specified "user object" assigned to the invoked google.script.run task runner (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);
}

Other refs

  • .withUserObject API
  • .withSuccessHandler API
  • Arrow fns

(It's theoretically possible you could use Function#bind to pre-pass some additional arguments to the function used as a success handler, but I haven't investigated that.)



来源:https://stackoverflow.com/questions/55432347/get-multiple-corresponding-values-from-different-html-tags-to-use-in-a-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!