Get Element Type from getComponents() array?

HI Folks I have this:

      $smForm = solutionModel.getForm($forms[i]);
                var $formElements = $smForm.getComponents()
                for (var c in $formElements)
                {
                     globals.output('Element = '+$formElements[c])
                }

I need to extract the element type from this I guess using the $formElements

 but I am struggling to see how to format this array selection to isolate the JSObject type?? So, is this element a button, a field etc.

Suggestions welcomed.

Ian

Hi Ian,
I’m afraid there’s no way to extract the component type.
Where do you want to use the type for?

HI Marc

Thanks for the reply - that’s what I anticipated - thought I might be missing something though.

We are experimenting with some new security and I am enumerating the forms and elements. Since we have been a bit lax in using a naming convention on some of the elements (ie but_ for buttons / lbl_ for labels etc) I was hoping to use the type to differentiate between them. We only want forms, buttons, tabs and fields, but I will be showing each type in a tab panel for ease of use from a security table.

Simply put, these forms and elements are being logged in a table so we can set permissions against the relevant types!

Is there another way to enumerate the type Marc?

I think there’s 2 ways:

  1. get all the components using the solutionModel, iterating the components set the name property with a name (if a name is not already specified)
    After that you can use forms[myForm].getElements, iterating this array you can use the function ‘getElementType’ to get the type.
  2. use the solutionModel and just ask for all the types you want (jsForm.getTabPanels(), jsForm.getButtons(), jsForm.getFields()), now you have all the elements sorted by type…

While using either option: after setting the name property, you could use ‘servoyDeveloper.save()’ function to write back all the solutionModel changes to the workspace again.
This should really just be a 1 time go in developer. Be careful, with this powerful option!

I’ve used this before, so if you need any help pls contact me and see if we can work this out.

Thanks Marc - tried 1. Perhaps my coding but the forms[myForm] format using the solutionModel to define the forms seems not to work!!

The second method you suggest is one McCourt has just used to work around it (bit slower than hoped but works).

Thanks for the pointers Marc - I’ll try that SM technique again as a test.

Cheers

Ian

Kahuna:
I need to extract the element type from this I guess using the $formElements

 but I am struggling to see how to format this array selection to isolate the JSObject type?? So, is this element a button, a field etc.[/quote]

There is no function on the JSComponent to get the type, but you can use the “instanceof” operator:

if (c instanceof JSLabel) {
     ...
} else if (c instanceof JSField) {
     ...
}

Thanks for that Joas - I hadn’t realised the components functions were so limited.

I also need to get the title text from the component but that appears to be even more difficult?

The reason we are going this way (solutionModel) is that we don’t want to touch each form when we iterate through them and enumerate the elements. But it would be useful if we could get the element tile text too.

Can you suggest a way to get this info without touching each form ?? (EDIT: Similarly the data provider for fields)

Cheers

Ian

A JSComponent is the superclass of components like JSLabel, JSField, etc. That’s why it only has the general functions and properties that all components have.
The JSField class has a lot more functions and properties, but you first need to know if your object is an instance of that class before you can safely use those.
That is where the instanceof operator comes in, because that can be used to determine if an object belongs to a certain class.

$smForm = solutionModel.getForm($forms[i]);
var $formElements = $smForm.getComponents()
for (var c in $formElements)
    if (c instanceof JSField) {
         var title = c.titleText; //titleText if is a property of JSField, but not of JSComponent
    }
}

Does this make things more clear?

Yes Joas - thanks - that makes things a little clearer.

I think I can navigate the elements with that structure now.

Cheers

Ian

Joas:
A JSComponent is the superclass of components like JSLabel, JSField, etc. That’s why it only has the general functions and properties that all components have.
The JSField class has a lot more functions and properties, but you first need to know if your object is an instance of that class before you can safely use those.
That is where the instanceof operator comes in, because that can be used to determine if an object belongs to a certain class.

$smForm = solutionModel.getForm($forms[i]);

var $formElements = $smForm.getComponents()
for (var c in $formElements)
if (c instanceof JSField) {
var title = c.titleText; //titleText if is a property of JSField, but not of JSComponent
}
}



Does this make things more clear?

Joas - having had the chance to test this format I am getting odd results.

With an app output on comnponets I get Element Type: [JSLabel[(TRUNCATED For Berevity) So I know its a label

But if I do this:

var $formElements = $smForm.getComponents()
globals.output('Element Typ: '+$formElements)     
for (var c in $formElements)
{
	if (c instanceof JSLabel) 
	{
	        var $elementType = 'JSLabel'
	        globals.output('Type Reported: '+$elementType)
	}
}

The code steps straight over the if, as if the component was not a label at all? What have I missed?

Hi Ian,

You handled the for-loop correctly the first time (see first post on this thread), Joas had that wrong. c in $formElements will return the position, not the object itself.
In some languages it does indeed return the object in the array (like Velocity for instance) but not JavaScript.
So your code should look like this:

var $formElements = $smForm.getComponents();
globals.output('Element Typ: '+$formElements);
for ( var c in $formElements) {
     if ( $formElements[c] instanceof JSLabel) {
          var $elementType = 'JSLabel';
          globals.output('Type Reported: '+$elementType);
     }
}

Hope this helps

Excellent thanks Robert - play with that in the am.

Cheers

Ian