Frank R.
Frank R.

Reputation: 23

Lifecycle of a dynamic created function in a for loop with eval

I am trying to create a dashboard for my classroom (async starting, async duration, async testing)...

My problem is I dynamicly create functions with eval (I know it's the way to the dark side). Do those dynamic created functions also no longer live then the for loop who they were created in?

     function onOpen() {
      const FUNC_STR = 'course';
      var evalString = '';
      const response = Classroom.Courses.list();
      const courses = response.courses;
      for(var index  in courses) {
        const course = courses[index]
        evalString += 'function ' + FUNC_STR + course.id + '() { ' + FUNC_STR + '(' + course.id + ') }';
        eval(evalString);
      }
      const ui = SpreadsheetApp.getUi();
      var mymenu = ui.createMenu('Classroom');
      if (courses && courses.length > 0) {
        for (i = 0; i < courses.length; i++) {
          const course = courses[i];
          mymenu.addItem(course.name, FUNC_STR + course.id);
          }
        mymenu.addToUi();
        }
    }
    function course(id ) {
      SpreadsheetApp.getActiveSheet().getRange('A1').setValue(Classroom.Courses.get(id).name);
    }

Upvotes: 0

Views: 86

Answers (1)

Tanaike
Tanaike

Reputation: 201553

I believe your goal as follows.

  • You want to create the custom menu on Google Spreadsheet when the Google Spreadsheet is opened.
  • You want to create the custom menu by dynamically creating the functions.

For this, how about this answer?

Modification points:

  • When the function is run from the custom menu, the function is required to be set to this of the script.
    • In your script, the functions of evalString += 'function ' + FUNC_STR + course.id + '() { ' + FUNC_STR + '(' + course.id + ') }'; is not set to this. So, when the function is run at the custom menu, the error occurs like "no functions".
  • In order to dynamically set the functions to the custom menu and run the function when the function is run at the custom menu, the function for installing the functions you want to run is required to be run, when the function is run at the custom menu.
    • In this case, it is not required to use eval.

When your script is modified, it becomes as follows. In this case, I propose the modified script by modifying the script of these answers. Ref1 and Ref2

Modified script:

Please copy and paste the following script to the script editor. And please run installFunctions() or reopen the Spreadsheet. By this, the custom menu is set. When you select the function from the custom menu, the function can be run.

installFunctions(); // This is required to run the function. So please don't remove this.
function onOpen() {} // This can be used as the simple trigger. So please don't remove this.

function installFunctions() {
  const FUNC_STR = 'course';
  const response = Classroom.Courses.list();
  const courses = response.courses;
  const menu = SpreadsheetApp.getUi().createMenu('Classroom');
  courses.forEach(e => {
    const functionName = `FUNC_STR${e.id}`;
    this[functionName] = () => course(e.id);  // Install the function.
    menu.addItem(e.name, functionName);
  })
  menu.addToUi();
}

// This is your function.
function course(id) {
  SpreadsheetApp.getActiveSheet().getRange('A1').setValue(Classroom.Courses.get(id).name);
}

Note:

  • In this case, it supposes that courses of const courses = response.courses; has the correct values and Classroom.Courses.get(id).name works. If an error occurs at them, please test the script using the simple values.

References:

Upvotes: 1

Related Questions