-1

I need a way to execute function that has parameters:

func1(param1, param2) 
{...
}

when I get the function name and its parameters as parameters (or string variables) in another function:

parentFunc()
{
  var funcName="func1";
  var params = {'param1': 'A', 'param2': 'B'}
   //Here I want to execute the funcName (func1) with its params.
}

I've tried creating customEvent, but the param didn't pass:

var event = new CustomEvent("func1", { 
  "param1": 'A', "param2": 'B'
});

this.element.dispatchEvent(event);//The element is the "parent" 
                                  //htmlElement that responsible to the 
                                  //event

*The functions are not in the same file and I'm doing in a Single Page Application (SPA), so doing it as shown below is not good enough:

var fn = window[settings.functionName];

Generally - what I'm trying to do is in a custom element - have the option to decide what function is executed (it is in the parent template) when there is event in the custom element

Guy E
  • 1,775
  • 2
  • 27
  • 55
  • 4
    You shouldn't really ever have to pass a function in the form of its name as a string. You can simply store the function: `var func = func1;` As for answering your question, it should work like this: `window[funcName](params.param1, params.param2);` –  Sep 25 '17 at 13:50
  • 1
    You should not choose a solution that will work with `window[settings.functionName]` will pollute the global namespace and that is something that you should always avoid. Beside that your script might break if you decide to use a minifcation tool. – t.niese Sep 25 '17 at 13:57
  • If you're using an SPA, use the corresponding mediator or pub/sub implementation to create an event that triggers that function. If without any of those, the function should be in scope of the module you're working on if your imported it correctly. Any more info about the architecture of the SPA framework you use? – Shilly Sep 25 '17 at 14:06
  • @Chris G - I can't send the function because the function (name) is set to a custom element attribute - the parent page set the attribute and the custom element should execute it. – Guy E Sep 26 '17 at 06:17
  • It seems like I wasn't clear enough - I need a custom element\control to run the function. The custome element doesn't "know" the function it should run - it depends on the parent page which send the name of the function as attribute to the custome element – Guy E Sep 26 '17 at 06:53
  • @GuyE Regarding your edit, I don't see how the things you mentioned preclude you from using `window[funcName]`? And maybe include what kind of templating system you're using that doesn't allow you to set, then use variables? I also get your frustration, but don't paste the same generic comment below each answer... I'm still 99% sure this is an [XY problem](http://xyproblem.info/), which is why people are talking about other solutions. –  Sep 26 '17 at 07:41

4 Answers4

1

Please consider sending something else to your function than the name of the function to execute. You can try for example a mapping between the condition and the function to execute. But if your heart is set on sending the function name or you have no way of not doing it that way, then your friend is the eval function :

function evaluate(name, params) {
    let toExecute = (name || 'eval') + '(';
    params = (params instanceof Object ? params : {});
    for (let key in params) {
        toExecute += params[key] + ', ';
    }
    if (toExecute[toExecute.length - 2] === ',') {
        toExecute = toExecute.substr(0, toExecute.length - 2);
    }
    toExecute += ');';
    eval(toExecute);
}

function parentFunc() {
    var funcName="func1";
    var params = {'param1': 'A', 'param2': 'B'}

    //Here I want to execute the funcName (func1) with its params.
    evaluate(funcName, params);
}

Please take a moment to read about the dangers of using eval here.

M0nst3R
  • 5,186
  • 1
  • 23
  • 36
  • I'de prefer not using eval, unless there is no other option. It seems like I wasn't clear enough - I need a custom element\control to run the function. The custome element doesn't "know" the function it should run - it depends on the parent page which send the name of the function as attribute to the custome element – Guy E Sep 26 '17 at 06:52
  • I would argue that custom element, being in charge of running the function, needs to know what it is beforehand. But If that is not possible, I really don't see anything except the `eval` function. – M0nst3R Sep 26 '17 at 08:38
  • Ghassen Louhaichi - see my solution below – Guy E Sep 26 '17 at 08:45
0

You can passed name function as param to callback:

parentFunc(funcName)
{
        var params = {'param1': 'A', 'param2': 'B'}
        funcName(params);
}

if you want function with params just:

parentFunc(funcName, param)
{            
        funcName(param);
}

parentFunc(func1, 'A')

Redair
  • 204
  • 1
  • 2
  • 12
  • Instead of `funcName` you should choose another name, because the name indicates that it is a name of a function and as of that a string. – t.niese Sep 25 '17 at 13:59
  • It seems like I wasn't clear enough - I need a custom element\control to run the function. The custome element doesn't "know" the function it should run - it depends on the parent page which send the name of the function as attribute to the custome element – Guy E Sep 26 '17 at 06:52
0

I didn't really understand what you're trying to accomplish by this. But I'd do something like this:

var myObject = {
  func1: func1
};

function parentFunc() {
  var funcName="func1";
  var params = {'param1': 'A', 'param2': 'B'};
  myObject[funcName](params.param1,params.param2);     
}

parentFunc();

function func1(param1, param2) {
  console.log(param1);
  console.log(param2);
}

hope it helps.

  • It seems like I wasn't clear enough - I need a custom element\control to run the function. The custome element doesn't "know" the function it should run - it depends on the parent page which send the name of the function as attribute to the custome element – Guy E Sep 26 '17 at 06:52
0

I managed to do it in Aurelia: This is the custom element with the foucusout.trigger which calls to the focusoutAction in the appropriate timing:

<template>
 <label>
   ${title} - ${fieldName}<input title.bind="title" 
   focusout.trigger="focusoutAction()" focusin.trigger="focusInAction()" 
   class="${cssClass}" />
  </label>
</template>

This is the usage of the custom element in the parent view with the focusout.call attribute:

 <form-input field-name="firstName" title="First Name" 
 place-holder="Enter first name" 
 on-focusout.call="validateInput(nameOfElement)" />

And this is the relevant code in the view model of the custom control:

@bindable onFocusout;

focusoutAction() {

   var args =
   {
      nameOfElement: this.fieldName
   };
   this.onFocusout(args);
}
Guy E
  • 1,775
  • 2
  • 27
  • 55