Specifying Data with Contextual References

In a contextual reference, PeopleCode refers to a row or buffer field determined by the context in which a PeopleCode program is currently executing.

This section includes an overview of current context and discusses how to:

  • Use contextual row references.

  • Use contextual buffer field references.

All PeopleCode programs, with the exception of programs associated with standard menu items, execute in a current context. The current context determines which buffer fields can be contextually referenced from PeopleCode, and which row of data is the current row on each scroll level at the time a PeopleCode program is executing.

The current context comprises a subset of the buffer fields in the component buffer, determined by the row of data where a PeopleCode program is executing. The current context includes:

  • All buffer fields in the row of data where the PeopleCode program is executing.

  • All buffer fields in rows that are hierarchically superior to the row where the PeopleCode program is executing.

Image: Context of PeopleCode executing on a level two scroll area

In the following diagram, all rows enclosed in dotted rectangles are part of the current context:

Context of PeopleCode executing on a level two scroll area

In the preceding diagram, a PeopleCode program is executing in a buffer field on row R3 on scroll level two. The rows in scroll level two are dependent on row R2 on scroll level one. The rows in scroll level one are dependent on the single row at scroll level zero. The current context consists of all the buffer fields at level two row R3, level one row R2, and level zero row R1. The rows in the current context on levels one and two are the current rows on their respective scroll areas. The single row on level zero is always current and is included in any current context. All rows other than the current rows and the level zero row are outside the current context. No current row can be determined on scroll areas below the one where the PeopleCode is executing.

With PeopleTools 8, contextual references work within the structure of a rowset object, and can include references to all field objects, record objects, row objects, and rowset objects in the current context.

Contextual Reference Processing Order

PeopleCode resolves contextual references at runtime by first checking the row where the PeopleCode program is executing. If PeopleCode does not find an appropriate buffer field, it looks in progressively higher rows in the current context. The following diagram indicates this processing order:

Image: Processing order of a contextual reference

The following diagram indicates the processing order of a contextual reference by PeopleCode program.

Processing order of a contextual reference

In typical pages, this processing order is not significant; however, if the same record occurs on more than one level of a page, you should understand how the direct reference is resolved.

A contextual row reference refers to a row in the current context on level one or lower in the page. Because each scroll area uses a unique primary record, the name of that record uniquely identifies whichever row is in the current context for that scroll level. A contextual row reference uses a RECORD. recordname component name reference to specify the scroll level of the intended row, resulting in a reference to the current row at the specified scroll level.

For example, you can use contextual row references with the RecordDeleted, RecordNew, and RecordChanged functions:

If RecordDeleted(RECORD.SOME_REC) Then...

With PeopleTools 8 object-oriented programming, a row can be referenced by specifying parent rows or rowsets of the current rowset:

If GetRowSet().ParentRowset.ParentRow.IsDeleted Then...

In early versions of PeopleTools, you could make contextual row references using a recordname.fieldname expression:

HideRow(SOME_REC.ANY_FIELD) 
If RecordDeleted(SOME_REC.ANY_FIELD) Then...

This syntax is still supported.

A contextual buffer field reference is a type of PeopleCode expression that refers to a buffer field by specifying a record field. The row of the buffer field is determined by the current context of the PeopleCode program where the reference is made. You can use a contextual buffer field reference to retrieve or update the value in the buffer field, to pass the buffer field value to a function, or to reference an instance of a page control associated with the buffer field. The following statements use contextual buffer field references:

/* Assigns value of variable to buffer field */
SOME_RECORD.SOME_FIELD = &VAL; 
/* Assigns value of buffer field to variable */
&VAL = SOME_RECORD.SOME_FIELD; 
/* Hides instance of control associated with buffer field */
Hide(SOME_RECORD.SOME_FIELD); 

With PeopleTools 8 object-oriented programming, a field object incorporates information about both the record field on which the buffer field is based and the page control with which the buffer field is associated. By referring to the field object, you either make a contextual buffer field reference or you change an interface attribute of the associated page control, depending on the object property you use. The following example has the same effect as a contextual buffer field reference:

/* Assigns value of a variable to a buffer field */
&MYFIELD.Value = &SOMEVAL;  

Contextual Buffer Field Reference Ambiguity

Nonprimary record fields may appear on more than one scroll level in a page. For example, a page may use a derived/work field DERIVED_JS.CALC_1 as a work field on level one and level two of the same page. This creates distinct DERIVED_JS.CALC_1 buffer fields for rows on both levels. Because of the order in which PeopleCode resolves contextual buffer field references, if the contextual reference &VAL = DERIVED_JS.CALC_1; executes in a PeopleCode program on a level-two row, the reference always retrieves the buffer field value on the current row on level two. PeopleCode on level two is unable to retrieve the value of the DERIVED_JS.CALC_1 on level one using a contextual reference.

To explicitly reference the DERIVED_JS.CALC_1 buffer field on level one, use a component buffer function with a scroll path:

&VAL = FetchValue(SCROLL.level1_scrollname, CurrentRowNumber(1), DERIVED_JS.CALC_1);

The CurrentRowNumber function returns the current row on level one, or the parent row of the level two row where the PeopleCode program is executing.

Ambiguous Contextual References to Buffer Fields on Level Zero

Level zero of a page contains only a single row of data, and the buffer fields in this row are always in the current context. For this reason you can almost always refer to a level zero buffer field using a contextual reference. However, referential ambiguity can make it impossible to reference a buffer field on level zero contextually. For example, a page may use a derived/work field DERIVED_JS.CALC_1 as a work field on level zero and level one of the same page. This creates distinct DERIVED_JS.CALC_1 buffer fields for rows on both levels. Because of the order in which PeopleCode resolves contextual field references, if the &VAL = DERIVED_JS.CALC_1; contextual reference executes in a PeopleCode program on a level-one row, it always retrieves the buffer field value on the current row on level one.

To explicitly reference the DERIVED_JS.CALC_1 buffer field on level zero, you must use a component buffer function with this syntax:

Function([recordname.]fieldname, rownum)

Here rownum, because it is on level zero, is always equal to one. In the previous example of the DERIVED_JS.CALC_1 field, you would use this statement:

&VAL = FetchValue(DERIVED_JS.CALC_1, 1);

Ambiguous References with Objects

With PeopleTools 8 object-oriented programming, even if two field objects that are in different rowsets contain buffer data that’s based on the same underlying record field, references to those objects are inherently unique, because each is instantiated with respect to a specific point in the hierarchy of the buffer. Any manipulation of a field object’s interface properties affects only the page control with which it’s associated.

The following example instantiates a field object using the long form, to emphasize the hierarchical form of the data. It then hides the field’s associated page control. Because this is a unique instance of the field, based on its hierarchy, hiding this field does not affect the visibility of any other page control associated with the same record field:

&MYFIELD = GetRowset(SCROLL.EMPL_CHECKLIST).GetRow(&I).
GetRecord(RECORD.EMPL_CHECKLIST).GetField(EMPL_CHECKLIST.EMPLID);
&MYFIELD.Visible = False;
/* the same code, using the "short" form */
&MYFIELD = GetRowset(SCROLL.EMPL_CHECKLIST).GetRow(&I).
EMPL_CHECKLIST.EMPLID;

Note: Any change in a field object’s value affects both the underlying record field and the value of any other field object oriented on the same record field. This behavior is the same as the behavior of contextual buffer field references that alter the field value.