Solution Model element not showing up on form

Hi All

When trying to add a button (reportsButton) with solution model code (see below) to a dynamically loaded form (i. e. with .addTab()), the button (or therefor any other element like field, label, …) is NOT showing up on the loaded form.
The wierd thing is, if I do make a change on the loaded form in the form designer and save the change, the reportsButton appears on the the form. This “trick” works only once, i. e. the first time making a change on the form and saving it.

// Load detail form PerMasterData
elements.tabDetail.addTab(forms.PerMasterData, null, null, null, null, null, null);

// Add the reports button to the corresponding form of the selected menu
history.removeForm(elements.tabDetail.getTabFormNameAt(1));
var detailForm = solutionModel.getForm(elements.tabDetail.getTabFormNameAt(1));
var onActionMethod = solutionModel.getGlobalMethod('onActionReportsFor2');
var reportsButton = detailForm.newButton(null, 0, 682, 40, 18, onActionMethod);

reportsButton.styleClass = 'Default';
reportsButton.borderType = 'EmptyBorder, 0, 0, 0, 0';
reportsButton.imageMedia = solutionModel.getMedia('btnReportGradient.png');
reportsButton.mediaOptions = SM_MEDIAOPTION.CROP;
reportsButton.anchors = SM_ANCHOR.WEST | SM_ANCHOR.SOUTH;
reportsButton.showClick = true;
reportsButton.showFocus = true;

application.updateUI();

Has anyone successfully added a (solution model) element to a loaded form? I also should mention, that the assigned method to the reportsButton does not execute ever (not even the single time the button appears on the form). What am I missing?

Best regards, Robert

I noticed the same situation, and I saw also that adding a new element using the solutionmodel is only possible if the form was created by the solution model.

What you do in your example is that you take an existing form and to this existing for you add a button.

I tried the same and I saw that this didn’t work, so my conclusion was that you can only put element on a form using the solutionmodel if the form itself was created by the solutionmodel.
I thought Servoy made it like this and I didn’t consider this as a bug.

I thought also that I could change the size of a (pre-designed) form using the solutionmodel, but that doesn’t work either.

I would like to know from the Servoy guys if the conclusion is right that the solutionmodel can only be used for forms created on runtime by the solutionmodel and the solutionmodel can not be used to changed predefined forms.

Martin

Hi Robert,

Robert Huber:
When trying to add a button (reportsButton) with solution model code (see below) to a dynamically loaded form (i. e. with .addTab()), the button (or therefor any other element like field, label, …) is NOT showing up on the loaded form.

I believe you are missing 2 bits of code for changing an existing (dynamic or not) form.

var sForm		= elements.tabDetail.getTabFormNameAt(1);
var detailForm 	= solutionModel.getForm(sForm);
history.removeForm(sForm);
solutionModel.removeForm(sForm); // <== remove the form from the solutionmodel

// start of your code
// ----------------------

var onActionMethod = solutionModel.getGlobalMethod('onActionReportsFor2');
var reportsButton = detailForm.newButton(null, 0, 682, 40, 18, onActionMethod);

reportsButton.styleClass = 'Default';
reportsButton.borderType = 'EmptyBorder, 0, 0, 0, 0';
reportsButton.imageMedia = solutionModel.getMedia('btnReportGradient.png');
reportsButton.mediaOptions = SM_MEDIAOPTION.CROP;
reportsButton.anchors = SM_ANCHOR.WEST | SM_ANCHOR.SOUTH;
reportsButton.showClick = true;
reportsButton.showFocus = true;

// end of your code
// ----------------------


// use this instead of application.updateUI (but will load it as frontmost form, perhaps for testing)
forms[sForm].controller.show();  
// or add it again to the tabpanel
elements.tabDetail.addTab(detailForm, null, null, null, null, null, null);

Hope this helps.

ROCLASI:

var sForm		= elements.tabDetail.getTabFormNameAt(1);

solutionModel.removeForm(sForm); // <== remove the form from the solutionmodel

Robert,

Why is this removeForm() necessary. I don’t see the use of it.

Martin

Hi Martin,

martinh:
Why is this removeForm() necessary. I don’t see the use of it.

You are absolutely right. This seems only needed when you are recreating the form (with the same name).

Hi Robert

Thanks for your suggestion, unfortunatly it still doesn’t work with your enhancements. The behaviour is still the same (the method assigned to the button is also still not executed).

Have you got more ideas to may be get it to work :-?

Thanks a lot for your help, Robert

Hi

If I can make the button appear on the form (see above) then when adding a name to the button, the onAction method is executed. BTW, giving the element a name is also necessary to make it work on a static form (created in the forms designer).

This line was necessary to make the onAction method work on the button if it’s visible (that problem is still not solved), but I’m one step further at least :-)

reportsButton.name = 'btnReportsForDomain2';

Regards, Robert

what does

history.removeForm(elements.tabDetail.getTabFormNameAt(1));

return?

does it return false or true?

Is the (main) form you are on visible? is the tab visible?

martinh:
I would like to know from the Servoy guys if the conclusion is right that the solutionmodel can only be used for forms created on runtime by the solutionmodel and the solutionmodel can not be used to changed predefined forms.

Johan,

Is what I write right or wrong?

Martin

Hi Johann

history.removeForm(elements.tabDetail.getTabFormNameAt(1)); returns false. Aha,is there a relation as history doesn’t work when loading, i. e. .addTab() forms dynamically?

The main form is always visible, as all forms are loaded into the main form parts (tabs). The form I load in this example is the form loaded into the detail part of the main form and has no tabs (this specific one).

BTW, the solutionModel.removeForm(sForm); also returns false!

Regards, Robert

jcompagner:
what does

history.removeForm(elements.tabDetail.getTabFormNameAt(1));

return?

does it return false or true?

Is the (main) form you are on visible? is the tab visible?

it can be used for predefined forms. But to make it easy. Only change the forms at solution load. Try to avoid touching forms in the middle of your solution.

The best thing to look at solution model is to see it in between the developer/designer and the Runtime. So between the 2, not mixed with runtime:
Developer/SolutionModel/Runtime

But if you are carefull it can work like:

Developer/SolutionModel/Runtime/SolutionModel/Runtime/SolutionModel/Runtime

But you need to be carefull. Only forms that are not visible anymore and can be removed by the history.removeForm() can be altered and made visible again with the changes you made to them at that later stage.

and as long as history.removeForm() return false
All the changes you will make to the form through solutionModel will not be reflected in the ui

The form must first be destroyed and reloaded again. And this is only possible if the form isnt visible anymore and can be removed through the history (returning true)

Hi Johann

Very interesting. As far as I found, history doesn’t work when loading forms dynamically, i. e. with .addTab like for example with elements.tabDetail.addTab(forms.PerMasterData, null, null, null, null, null, null);

So I assume that’s why elements.tabDetail.addTab(forms.PerMasterData, null, null, null, null, null, null); returns false. Is that correct?

Does that mean changing predefined forms dynamically loaded is not possible at all?

Regards, Robert

jcompagner:
it can be used for predefined forms. But to make it easy. Only change the forms at solution load. Try to avoid touching forms in the middle of your solution.

The best thing to look at solution model is to see it in between the developer/designer and the Runtime. So between the 2, not mixed with runtime:
Developer/SolutionModel/Runtime

But if you are carefull it can work like:

Developer/SolutionModel/Runtime/SolutionModel/Runtime/SolutionModel/Runtime

But you need to be carefull. Only forms that are not visible anymore and can be removed by the history.removeForm() can be altered and made visible again with the changes you made to them at that later stage.

if tabpanel.addTab(xxx) does return false then the tab isnt added at all.
This can have multiply reasons like the form isnt found or the forms table isnt the related table of a relation if you would give that.
This doesnt have anything to do with solution model

And again i did say that already. changing predefined forms can be done fine they only cant be visible and should be able to be removed by the history object.
Again they cant be visible!

Hi Johann

May be you missunderstood me, but tabpanel.addTab(xxx) returns true of course and yes I understand that it has nothing to do with the solution model per se.

jcompagner:
if tabpanel.addTab(xxx) does return false then the tab isnt added at all.
This can have multiply reasons like the form isnt found or the forms table isnt the related table of a relation if you would give that.
This doesnt have anything to do with solution model

I don’t understand what you are saying below, sorry. What exactly do you mean by: changing predefined forms can be done fine they only cant be visible? This makes no sense, does it? If I can change a predefined form but never make the changes visible, how is this of any use? Of course I have to make the changes visible to the user.

jcompagner:
And again i did say that already. changing predefined forms can be done fine they only cant be visible and should be able to be removed by the history object.
Again they cant be visible!

Regards, Robert

its simple if you want to change a form then you first must make sure that that form is not visible at the time you want to change it
So first go to another main form or select another tab so that the form is not in the selected tab.
Only then you can change your form and the reshow it again as a main form or in a tab.

This discussion only makes it more clear that you shouldnt really touch your forms at runtime
Only “pre” runtime, Then it is simple, change or create forms the way you want before you show anything
then it just always works.

Hi Johann

I got it to work! Here is (the modified) code for those interested, first the method to add the button (it’s an image) to the form:

function smMenuReportsForDomain()
{
	/*
	Title:		The button with menu reports for the domain will be dynamically created with the solution model.
	
	Author:		Robert Huber
	Created:		09.06.2009
	Modified:		-
	
	Arguments:	Form to display button menu reports, onAction method name
	Returns:		-
	Notes:		-
	*/
	
	var smForm = solutionModel.getForm(arguments[0]); // Get form to add menu reports to
	var onActionMethod = solutionModel.getGlobalMethod(arguments[1]); // Get onAction method name
	var btnReports = smForm.newButton(null, 0, 682, 40, 18, onActionMethod); // Create button and attach onAction method to it, e. g. onActionReportsForDomain2

	// Set properties for menu reports button
	btnReports.name = 'btnReports';
	btnReports.styleClass = 'Default';
	btnReports.borderType = 'EmptyBorder, 0, 0, 0, 0';
	btnReports.imageMedia = solutionModel.getMedia('btnReportGradient.png');
	btnReports.mediaOptions = SM_MEDIAOPTION.CROP;
	btnReports.anchors = SM_ANCHOR.WEST | SM_ANCHOR.SOUTH;
	btnReports.showClick = true;
	btnReports.showFocus = true;
}

and then the onAction method to create the menu entries from a database table:

function onActionReportsForDomain2()
{
	/*
	Title:		Popup menu for all reports in domain persons
	
	Author:		Robert Huber
	Created:		09.06.2009
	Modified:		-
	
	Arguments:	-
	Returns:		-
	Notes:		-
	*/
	
	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(i18n.getI18NMessage(report_name[i]), globals[report_method[i]]);
	}

	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);
	}

Best regards, Robert

jcompagner:
its simple if you want to change a form then you first must make sure that that form is not visible at the time you want to change it
So first go to another main form or select another tab so that the form is not in the selected tab.
Only then you can change your form and the reshow it again as a main form or in a tab.

This discussion only makes it more clear that you shouldnt really touch your forms at runtime
Only “pre” runtime, Then it is simple, change or create forms the way you want before you show anything
then it just always works.

Hi

I am stucked again at displaying an image on a form as I do with a button.

Solution model gives the following info for image media and button:

.newImageMedia(dataprovidername/jsvariable, number x, number y, number width, number height)
.newButton(text, number x, number y, number width, number height, jsmethod)

This code works:

var paneFooter = smForm.newButton(null, btnPosX + 40, btnPosY, 820 - btnPosX, 18, null);
	
	// Set properties for pane footer (gradient) graphic
	paneFooter.name = 'paneFooter';
	paneFooter.styleClass = 'Default';
	paneFooter.borderType = 'EmptyBorder, 0, 0, 0, 0';
	paneFooter.imageMedia = solutionModel.getMedia('paneFooterGradientBG.png');
	paneFooter.mediaOptions = SM_MEDIAOPTION.ENLARGE;
	paneFooter.anchors = SM_ANCHOR.WEST | SM_ANCHOR.SOUTH | SM_ANCHOR.EAST;
	paneFooter.showClick = false;
	paneFooter.showFocus = false;

This code doesn’t work, so there must be something wrong in giving the image as an argument (first argument) to the method. I tried various ways but no success. May be someone found a way?

	var paneFooterImage = "media:///paneFooterGradientBG.png";
	var paneFooter = smForm.newImageMedia(paneFooterImage, btnPosX + 40, btnPosY, 820 - btnPosX, 18); // Create footer graphic
	
	// Set properties for pane footer (gradient) graphic
	paneFooter.name = 'paneFooter';
	paneFooter.styleClass = 'Default';
	paneFooter.borderType = 'EmptyBorder, 0, 0, 0, 0';
	paneFooter.imageMedia = solutionModel.getMedia('paneFooterGradientBG.png');
	paneFooter.mediaOptions = SM_MEDIAOPTION.ENLARGE;
	paneFooter.anchors = SM_ANCHOR.WEST | SM_ANCHOR.SOUTH | SM_ANCHOR.EAST;
	paneFooter.showClick = false;
	paneFooter.showFocus = false;

Best regards, Robert

you are giving yourself your anwser:

this is the call:

.newImageMedia(dataprovidername/jsvariable, number x, number y, number width, number height)

So the first argument must be a dataprovider or a dataprovider wrapped as a JSVariable…
and this:

var paneFooterImage = “media:///paneFooterGradientBG.png”;

is not a dataprovider or a dataprovider wrapped as a JSVariable.

and JSForm.newImageMedia() creates a field for data entry. not a label/button that displays a Image…
So what you do exactly want?

Ah, I see, I missunderstood .newImageMedia(), it is the special form of newField, could be named newImageMediaField, could it?

What I would like to display is an image on the footer part. So I assume this actually is .newLabel (which seems to be the same as newButton, except the last parameter (jsMethod) is optional)

It seems that .newLabel is intended to display an image?

Regards, Robert

jcompagner:
you are giving yourself your anwser:

this is the call:

.newImageMedia(dataprovidername/jsvariable, number x, number y, number width, number height)

So the first argument must be a dataprovider or a dataprovider wrapped as a JSVariable…
and this:

var paneFooterImage = “media:///paneFooterGradientBG.png”;

is not a dataprovider or a dataprovider wrapped as a JSVariable.

and JSForm.newImageMedia() creates a field for data entry. not a label/button that displays a Image…
So what you do exactly want?