Monday, May 24, 2010

Disabling all fields in a component using a recursive method

Greetings! This is my first post on my rants on peoplcode and other peoplesoft related tools.

To start, here is an interesting problem. There is a requirement to disable all fields in a component except for a few buttons and dropdowns. The most obvious solution is to disable all pages in the component by setting the page's DisplayOnly property like this:

GetPage(Page.).DisplayOnly = True;

This only takes us halfway there. We need some of the fields on the page to be enabled. Now, if these fields are buttons then its easy, just set the page field property 'Enable when Page is display only'. Done.

But, if the fields that should remain enabled are dropdowns or edit boxes then disabling the page is not a solution. There is no page field option to enable these fields when the page is disabled. Additionally, when a page is disabled, some tools buttons like 'Save' also get disabled. yikes!

So, the only thing left for us now is to individually disable all fields in the component from level 0 to level n. This gives us the flexibility to leave out fields we don't want to touch. This is easy if the number of records and levels in the component is small. But in a large component this can be frustrating and it would be unmanageable in the long run. Just imagine the confusion if a new field is added to one of these pages later.

Here is a quicker way to do this:

method setRowsetFieldDisplayOnly
/+ &p_rs as Rowset, +/
/+ &p_displayOnly as Boolean +/

Local number &i, &j, &k;

/*disable itself*/
For &i = 1 To &p_rs.ActiveRowCount
For &j = 1 To &p_rs(&i).RecordCount
For &k = 1 To &p_rs(&i).GetRecord(&j).FieldCount
If Not (%This.isRecordFieldExcluded(&p_rs(&i).GetRecord(&j).Name | "." | &p_rs(&i).GetRecord(&j).GetField(&k).Name) Or
%This.isFieldExcluded(&p_rs(&i).GetRecord(&j).GetField(&k).Name)) Then
&p_rs(&i).GetRecord(&j).GetField(&k).DisplayOnly = &p_displayOnly;
End-If;

End-For;
End-For;
End-For;

/*Disable child rowsets*/
For &i = 1 To &p_rs.ActiveRowCount
For &j = 1 To &p_rs(&i).ChildCount
%This.setRowsetFieldDisplayOnly(&p_rs(&i).GetRowset(&j), &p_displayOnly);
End-For;
End-For;

end-method;


This method loops through all levels starting from level 0 and disables each record field individually. Moreover, as this is a recursive method we don't have to know how many levels and child rowsets there are in the given component. This make it generic and can be used in any component. To exclude fields from being modified, this method check if the field names or record field names exist in an array of strings. There, that should take care of our requirements.