Hi
I read the method (name) from a table column called “report_method”. I would like to use that method name in the popup menu plugin:
plugins.popupmenu.createMenuItem(menuName, methodName);
But it doesn’t work (see complete code at bottom). I assume the reason is the methodName parameter is not recognized as a method name, because it’s a string I read from the table.
As an example, if report method is the string reportTest, read from the table, the method is not executed.
* <em>reports <em>= plugins.popupmenu.createMenuItem(report_name<em>, report_method*);*</em></em></em> <em><em>_*
If I hard code it as follows, it’s executed.
*_</em></em> <em><em><em><em>reports <em>= plugins.popupmenu.createMenuItem(report_name*, reportTest);*</em></em></em></em></em> <em><em><em><em>_*
How can I let Servoy interprete report_method as a method?
```_
*var formName = application.getMethodTriggerFormName(); // Get name of form this method is called from
// Get report data for this domain from table report_assignments
var query =
" SELECT menu_id, school_unit_id, sort_order, report_name, report_method" +
" FROM report_assignments" +
" WHERE menu_id = 2" +
" ORDER BY sort_order";
var dataset = databaseManager.getDataSetByQuery(forms.PerMasterData.controller.getServerName(), query, null, 1000);
var report_name = dataset.getColumnAsArray(4);
var report_method = dataset.getColumnAsArray(5);
var reports = new Array();
// Build popup menu reports
for (var i = 0; i < dataset.getMaxRowIndex(); i++)
{
reports[i] = plugins.popupmenu.createMenuItem(report_name[i], report_method[i]);
//reports[i] = plugins.popupmenu.createMenuItem(report_name[i], reportTest);
}
var element = forms[formName].elements[application.getMethodTriggerElementName()]; // Get element (btnReports) for it's coordinates to display popup menu at the correct position
if (element != null)
{
plugins.popupmenu.showPopupMenu(element, reports);
}*</em></em></em></em></em></em>
```
Best regards, Robert
Hi Robert,
as long as your string really reflects a function by that name and that you prefix it depending on the context - globals.method, or method, or forms.anotherform.method - without the parenthesis -, it should work fine with the eval() function.
Try it in your loop like this:
reports <em>= plugins.popupmenu.createMenuItem(report_name<em>, eval(report_method*));*</em></em>
<em>_*```*_</em>
<em>_*Hope this helps,*_</em>
Robert,
You can also lookup the method in the appropriate scope.
For form methods: reports <em>= plugins.popupmenu.createMenuItem(report_name<em>, forms.report_form[report_method*)]);*</em></em> <em>_*
or for global methods:
*_</em> <em><em><em>reports <em>= plugins.popupmenu.createMenuItem(report_name<em>, globals[report_method*)]);*</em></em></em></em></em> <em><em><em><em>_*
*
Rob_
Hi Patrick
Thanks, your idea works! I have to say that as Rob’s idea works as well, I have chosen that one, as I try to avoid to use eval, because I am not very sure about the properties eval() has. But may be it’s just some sort of a lesser good feeling for that method .-)
Best regards, Robert
ptalbot:
Hi Robert,
as long as your string really reflects a function by that name and that you prefix it depending on the context - globals.method, or method, or forms.anotherform.method - without the parenthesis -, it should work fine with the eval() function.
Try it in your loop like this:
reports <em>= plugins.popupmenu.createMenuItem(report_name<em>, eval(report_method*));*</em></em>
<em>_*```*_</em>
<em>_*Hope this helps,[/quote]*_</em>
Hi Rob
Thanks for pointing me to that solution, it works and does what I was looking for. By the way, for others, it should read like this (see the missing “)” near the end):
reports <em>= plugins.popupmenu.createMenuItem(report_name<em>, forms.report_form[report_method*]);*</em></em>
<em>_*``` or*_</em>
<em>_*```*_</em>
<em><em><em>reports <em>= plugins.popupmenu.createMenuItem(report_name<em>, globals[report_method*]);*</em></em></em></em></em>
<em><em><em><em>_*```*_</em></em></em></em>
<em><em><em><em><em><em>By the way, as report_name *is a i18n key, one can clarify it by writing it like:*</em></em></em></em></em></em>
<em><em><em><em><em>_*```*_</em></em></em></em></em>
<em><em><em><em><em><em><em>reports <em>= plugins.popupmenu.createMenuItem(i18n.getI18NMessage(report_name<em>), forms.report_form[report_method*]);*</em></em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em>_*```*_</em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em>_*I actually don't know why both ways work, but may be you can clarify it, why the i18n.getI18NMessage() method actually is not necessary to get the same result?*_</em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em>_*Best regards, Robert*_</em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em>_*> rgansevles:*_</em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em>_*> Robert,*_</em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em>_*>*_</em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em>_*> You can also lookup the method in the appropriate scope.*_</em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em>_*>*_</em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em>_*> For form methods: ```*_</em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em><em><em>> reports <em>= plugins.popupmenu.createMenuItem(report_name<em>, forms.report_form[report_method*)]);*</em></em></em></em></em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em><em><em>> <em>_*```*_</em></em></em></em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em><em><em>> <em>_*or for global methods:*_</em></em></em></em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em><em><em>> <em>_*```*_</em></em></em></em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em><em><em>> <em><em><em>reports <em>= plugins.popupmenu.createMenuItem(report_name<em>, globals[report_method*)]);*</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em><em><em>> <em><em><em><em>_*```*_</em></em></em></em></em></em></em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em><em><em>> <em><em><em><em>_*Rob[/quote]*_</em></em></em></em></em></em></em></em></em></em></em></em></em></em>
Robert Huber:
Thanks, your idea works! I have to say that as Rob’s idea works as well, I have chosen that one, as I try to avoid to use eval, because I am not very sure about the properties eval() has. But may be it’s just some sort of a lesser good feeling for that method .-)
Hi Robert,
I understand your feeling about the eval() function, but in that case, providing that you are the one feeding it with your own “checked” values (and not “user typed” values), it’s perfectly safe.
And it has the advantage of using only one line for different scopes (globals, forms and currentForm) depending on what’s in the String, it’s just more “dynamic” this way, which is what JavaScript is all about IMHO.
Glad that it works anyway!
Hi Patrick
Thanks for that very interesting view related to eval vs “the other” notation! You mention an interesting aspect - “more” dynamic vs “more” typified, one could say. BTW, does “the other” notation have a name?
Regards, Robert
ptalbot:
Hi Robert,
I understand your feeling about the eval() function, but in that case, providing that you are the one feeding it with your own “checked” values (and not “user typed” values), it’s perfectly safe.
And it has the advantage of using only one line for different scopes (globals, forms and currentForm) depending on what’s in the String, it’s just more “dynamic” this way, which is what JavaScript is all about IMHO.
Glad that it works anyway!
In that case specifically, I would say “static”, the code is fixed, and the path that the program will take will be determined at “coding” time.
For example, to be able to handle each of the case I gave (passing either global methods, other forms methods and current form method), you would have to add tests (case statements or a serie of if else statements) in Rob’s proposed approach, so you are really predetermining the behavior of your program that way, while the use of eval() make it more “dynamic”, more undeterministic even, there is no need of any case statements or if()…else statements!
Any way you do it will works, and Rob’s approach is going to be the preferred way if the Strings are not safe, clearly eval() is not the kind of function that you will use directly on user input, but otherwise eval() is a nice function of the JavaScript language and I see no reason not to use it (you can enclose it inside try catch statements if you fear that some string might be invalid - but that would be true anyway if you give him a method name with a typo).
One could compare the way JavaScript being not “typed” (your var can contain any kind of value) is more dynamic than Java for exemple which is a “typed” (constrained) language. Each approach has its advantages and its drawbacks.
You could say that the strength of Java is precisely because it is a typed language, while others would argue that being non-typed give JavaScript all its advantages…
It is an open debate, and I’m sure that you can find many discussions about that on the internet if you are interested.
The good thing is that in Servoy you can have the best of both worlds!
Hi Robert,
following this discussion, I have made some tests, and I ended up with a little sample solution that I think some people will find interesting (it’s full of nice tricks that you will certainly know about but that some Servoy newcomers will certainly appreciate).
Basically, it is a navigation/menu automated system, i18n aware, servoy groups security aware, driven by a database and that works in the Smart AND the Web client.
You can find more info about it, and download the solution from this page of the Servoy Stuff web site.
Cheers,