Today I was debugging an issue where in a ghost row is getting inserted into the grid in level 2 even if the user is not entering any value for the grid in level 2. There are many instances where you find the ghost row issue in PeopleSoft. This one was particular to the sequencing number and which is almost a common case across the product. So I will explain a bit about the ghost row issue with the particular case.
The page has a structure up to level 3. And my level 2 additional key is a sequence number which is auto populated by the system. Now when the user goes in add mode and enter any data up to level 1 (assuming he is adding only one row which is presented by default) and saves the page, then everything seems fine. The data up to level one is inserted into the database as user has filled only up to level 1.
Now if he tries to add another row at level one and enter data only in level 1 or if he just clicks the + button on the level 2 of the level 1 first row, then a ghost row of level 2 is getting inserted into the database even though user has not entered any data into the level 2 rows.
The reason for the ghost row is the sequencing logic written in RowInsert event. Since the additional key for level 2 is a sequence number which is populated automatically by the system, whenever the sequencing logic executes and assigns a value from the RowInsert event, the system automatically sets that particular row as changed and will mark it for database insert during the time of save.
Most of the places where auto sequencing is used, the sequence number field is read only and user cannot delete its value thus forcing the system to insert the row into database; making the case more complicated.
PeopleBooks has clearly mentioned that if you change the value of any field in the RowInit or RowInsert events, the system will mark the row as changed and will be considered during the save processing.
But in most cases, you are forced to write the logic in RowInsert event because it is apt to display the next sequence number whenever user clicks the plus button.
Now back to the issue why there was no ghost row inserted my first default row at level 1? The reason is pretty straight forward, the RowInsert event will get fired only when the user adds a row, for default rows that event is ignored.
This might be a well known situation so that PeopleTools has provided the solution for the problem as well. There is a delivered property for rowset class called ChangeOnInit. All you need to do is to set that property to false during the component load processing or during the RowInit processing of the higher level (in my case it is level 1). Once this property is set to false, the component processor will no longer mark the row as changed whenever a field value is programmatically updated in RowInit or RowInsert events, thereby that row will not be considered for database insert until and unless user updates any value on the field. This is a pretty handy property which avoids programmatic defaults be inserted into the database when it is not actually supposed to be inserted. Thus, this one line code will take away the headache. You can see the sample code given below which will address the given situation of ghost row.
rem This code should be written on the RowInit of the primary record one level up;
rem In this case code is written at Level 1 to resolve ghost row issue at level 2;
GetRow().GetRowset(Scroll.LEVEL2_REC).ChangeOnInit = False;