Solution Model Guidance?

Hi Folks - in line with a few other questions I’ve raised this week already, some guidance on the concepts of the solution model would be welcomed.

Q. If an onLoad method already exists on a form how can I integrate my solution model code into it, to run in parallel consecutively? Or is this only possible where there is no onload method in place already

Q. If there is a method in the onLoad event of a form with a different name than onLoad, how should that be referenced?

Q. Does the .getFormMethod(‘function onLoad (event)}’) integrate the code with the current onLoad function somehow?

Q. Is this the correct syntax to reference an element on a form in SM in an onLoad event?

_jsForm.onLoad = _jsForm.newFormMethod('function onLoad (event){.elements[buttonName]enabled = false}')

Feedback Welcome.

Hi Ian,

If I’m reading your post, I get the idea that you’d like to assign a newly defined onLoad method to the onLoad event of all/some of your existing forms.
but…

  1. you already have forms with an existing method assigned to the onLoad event
  2. these methods might have a different name than ‘onLoad’

Basically you want to add the existing code to the newly defined onLoad method.

Is this correct?

mboegem:
Hi Ian,

If I’m reading your post, I get the idea that you’d like to assign a newly defined onLoad method to the onLoad event of all/some of your existing forms.
but…

  1. you already have forms with an existing method assigned to the onLoad event
  2. these methods might have a different name than ‘onLoad’

Basically you want to add the existing code to the newly defined onLoad method.

Is this correct?

Correct - though I cant loose the code already assigned to the onLoad event - does that make sense Marc??

If I understand correctly, I think this is what you are looking for

var _jsForm = solutionModel.getForm(formName)

var currentOnLoad = _jsForm.onLoad; //Gets the JSMethod attached to the forms onLoad event (if it exists) 
var newOnLoad;
var code;
if (currentOnLoad)	//an onLoad method exists, so we must add a call to it in our custom code.
{
	code =	"function myHighlyUniqueFormMethodNameToAvoidCollisions(event) {\n" +
     		" //Some code that does things\n" +
     		currentOnLoad.getName() + "(event);\n" +	//This line adds a call what whatever the existing onLoad was.
     		"//code that does more things\n" +
     		"}";
 	 
}
else	//There was no existing onLoad, so just do our own code.
{
	code =	"function myHighlyUniqueFormMethodNameToAvoidCollisions(event) {\n" +
     		" //Some code that does things\n" +
     		"//code that does more things\n" +
     		"}";
}
newOnLoad = _jsForm.newFormMethod(code);
jsForm.onLoad = newOnLoad; //set the onLoad to our new JSMethod

jgarfield:
f I understand correctly, I think this is what you are looking for

This could be a way, though 1 nice challenge: the ‘currentOnLoad.getName()’ gives you just the name, not the scope.
So in case this is a global method, the call to this method will end nowhere.

Personally I’d create 1 global onLoad method which checks the existence of a certain formMethod and calls it in case it exists.
Now the challenge: make existing functions into new ones with the ‘myHighlyUniqueFormMethodNameWhichDoesntExistAnywhereOnASingleForm’ name
but that’s not the hardest part, in fact: very easy.

So 1 global onLoad method, which even could be created at designtime:

function onLoad(event)
{
	var $form = event.getFormName();
	
	if(forms[$form].onPreLoad)
	{
		forms[$form].onPreLoad(event);
	}
}

then the James’ method with a slight change:

var _jsForm = solutionModel.getForm(formName)

    var _currentOnLoad = _jsForm.onLoad; //Gets the JSMethod attached to the forms onLoad event (if it exists)
    var _newOnLoad = solutionModel.getGlobalMethod('onLoad');
    var _code;
	var _name
    if (_currentOnLoad)   //an onLoad method exists, so we must add a call to it in our custom code.
    {
	   _name = currentOnLoad.getName();
       _code = currentOnLoad.code;
	   _code = _code.replace(/\s\* @properties?[^}]+(}\n|$)/g, ''); //strip the @properties tag
       _code = utils.stringReplace(_code, 'function ' + _name, 'function onPreLoad');
	   
	   _jsForm.newFormMethod(_code)
    }
    
    jsForm.onLoad = _newOnLoad; //set the onLoad to our new JSMethod

A 2nd option is just to go through all your forms and manually do the above.
Might be some work, but at least you don’t have to bother about that anymore in your code…

Hope this helps…

Thanks James & Marc - sorry but I’m not clear.

I see where you are going with the function replacement Marc - but it’s shady on two points:

  1. Where in your code do I inject the new functionality (which happens to be enabling and disabling entire forms and in some cases just buttons on forms).

  2. How do I reference an element on a form is a solution model method - all syntax I’ve tried has failed so far?

Really appreciate you taking your time to educate a slow learner! :D

Additionally I need to alter the same method several times (if code calls for it) so I find using James code as a learning process I’m attempting to save the _newOnLoad with the same name twice - and Servoy does not like that at all!!!

I suspect a prefered method would be to actually be able to parse the code in the current onLoad method and add the necessary code before the last ‘}’.
Any thoughts on that route?

Further Testing:
The following code does not elicit the method name in the onLoad event of the form though I know there is one (not called onLoad) and tried with a hard coded form name - am I missing some thing really obvious here???:

var _jsForm = solutionModel.getForm(formName)
	
						var currentOnLoad = _jsForm.onLoad;

Hi Ian,

  1. I start off with just one global method called ‘onLoad’ which tries to call an ‘onPreLoad’ method on the various forms.
    That’s why I rename the existent methods bound to the onLoad event to ‘onPreLoad’ (assuming you don’t have any form method named that way)
    The new global ‘onLoad’ method is to be bound to the onLoad events.

  2. You mean binding a method to the onAction event of an element?
    First create or reference a JSMethod object and set the elements property with it. So:

var _jsForm = solutionModel.getForm('myForm')
var _jsButton = _jsForm.getButton('myButton')
var _jsMethod = _jsForm.getFormMethod('myFabulousFunction')

_jsButtton.onAction = _jsMethod;

You are saying you want to alter the same method several times.
This is not really a problem when you alter a global method, but as soon as you’ve altered a form method you need to call ‘controller.recreateUI()’

Besides: if you want to alter a method you must start off by checking if this method already exists. If it does: get the method as JSMethod and set the ‘code’ property with the new code. Otherwise: create the JSMethod with the code you need to go in there.

Just curious: what are you trying to achieve by altering methods over and over again?

mboegem:
Just curious: what are you trying to achieve by altering methods over and over again?

Thanks Marc - I’m still working on a simpler way to set our security and login. You showed me some solutionModel code that I have been playing with.

So at login we read the permissions table which will have buttons and forms that will be enabled and dissabled. For some forms there will be 9 or 10 buttons to dissable and perhaps the form will be disabled too. So that could feasibly be 11 mods to the onLoad event, and keeping it simple we are simply looping through the table.

I’m not looking at the onAction event at all.

I made some further comments whilst you were writing your response Marc and I suspect I’m off on a completely wrong track because some of the forms I’m referencing that have known onLoad events dont show with this code. This is a global function called on login as a test

var _jsForm = solutionModel.getForm('comp_frm_main')
			var currentOnLoad = _jsForm.onLoad;

Not sure why yet. Been a long day and this seems like a particularly thorny challenge :shock: :D

Kahuna:
So at login we read the permissions table which will have buttons and forms that will be enabled and dissabled. For some forms there will be 9 or 10 buttons to dissable and perhaps the form will be disabled too. So that could feasibly be 11 mods to the onLoad event, and keeping it simple we are simply looping through the table.

To keep things even more simple, why not directly alter the form based on the settings you retrieve?
No need for any magic with the onLoad event.
This will mean you can’t use runtime properties like ‘enabled’, but in case you are changing the visibility: why not just remove the whole button from the form?
Otherwise: yes, you have to generate the ‘onLoad’ code. Even then I’d try to group my actions per form, so the alterations can be done in 1 go.

note: Servoy 6 will have more ‘Servoy 5 runtime properties’ as designtime properties.
for example: the ‘visible’ and ‘enabled’ property can be set as a designtime property of the element.
this also means: they are available to the solutionModel.
In that case you probably will be able to do all your stuff at startup.

Kahuna:
I made some further comments whilst you were writing your response Marc and I suspect I’m off on a completely wrong track because some of the forms I’m referencing that have known onLoad events dont show with this code. This is a global function called on login as a test

Code: Select all
var _jsForm = solutionModel.getForm(‘comp_frm_main’)
var currentOnLoad = _jsForm.onLoad;

your code looks ok to me, but maybe it’s the result you expect that is different from what it does.
based on the code above, you will end up with a currentOnLoad variable which references a JSMethod.
so:

application.output(currentOnLoad.getName())

should print the methodname in your console.

Hope this helps

I see where you are at Marc - but with more testing I see that if I place this code in a form I get the expected results as you suggest, but when the code is in a global then it does not find the methods

This

var _jsForm = solutionModel.getForm('sandbox_ians')
		var currentOnLoad = _jsForm.onLoad; //Gets the JSMethod attached to the forms onLoad event (if it exists) 
		application.output(currentOnLoad.getName()+ ' ' + currentOnLoad.code)

results in this when run in a form (not in the globals space)

onLoadNewTestName /**
 * Callback method when form is (re)loaded.
 *
 * @param {JSEvent} event the event that triggered the action
 *
 * @properties={typeid:24,uuid:"3227299B-7C71-43A0-8CAA-9964918346F0"}
 */
function onLoadNewTestName(event) {
	application.output('Sandbox Loaded')
}

currentOnLoad is always null when run in the globals space (tried it in a module global and main solution global. Have you tried it in a globabls space Marc??

I’am still a little confused about how, in your scenario, I would place the form modification code? I have the method code, and I have the method name, I’m able to save the method as a new name onPreload in your example. But where do I insert my button and form enable = false type of code???

Kahuna:
currentOnLoad is always null when run in the globals space (tried it in a module global and main solution global. Have you tried it in a globabls space Marc??

That’s what I do every day.
For slight customization we use the solutionModel to alter/add methods (depending on a default situation or not)
These are a mix of global/form methods, but all executed from a global scope.

mboegem:
That’s what I do every day.
For slight customization we use the solutionModel to alter/add methods (depending on a default situation or not)
These are a mix of global/form methods, but all executed from a global scope.

Thanks Marc, obviously more testing this morning for sure - but it’s definitely returning null for currentObLoad when run from globals space as opposed to the correct result when run from a form.

However - can you guide me on how to modify the code in the current onLoad event and then save it back.

Is it literally get the code, strip off the last ‘}’, insert my code and re-add the ‘}’ then save the method back???.
And if so, is the saving of the method simply

_code = ‘oldCode + newCodeForMethod’
_jsForm.originalFormMethodName(_code)

or do I need to overtly save that data back to the original method?

Hi Ian,

just to tackle the problem you seem to have checking the formMethod from a global scope: take a look at the attached solution.
This works for me (at least I see the output…)
Hope this is a first step in the right direction.

checkOnLoad.servoy (3.35 KB)

Kahuna:
However - can you guide me on how to modify the code in the current onLoad event and then save it back.

Is it literally get the code, strip off the last ‘}’, insert my code and re-add the ‘}’ then save the method back???.
And if so, is the saving of the method simply

_code = ‘oldCode + newCodeForMethod’
_jsForm.originalFormMethodName(_code)

or do I need to overtly save that data back to the original method?

See the attached solution.
Just basic, but you’ll get the concept.

alterOnLoad.servoy (3.47 KB)

mboegem:
See the attached solution.
Just basic, but you’ll get the concept.

Thanks Marc - we are playing with that now. Really appreciate your support thanks again.

Brilliant Marc - many thanks my friend - great guidance.

You’re all MVP’s to me :D :D :D :D