Extend the sample procedures to track changes
- Last Updated: March 30, 2020
- 4 minute read
- OpenEdge
- Version 12.2
- Documentation
You can track changes in a ProDataSet to extend the sample window dsOrderWin.w and its supporting procedures:
To track changes in the ProDataSet:
-
Save a new version of the window procedure
dsOrderWin.wasdsOrderWinUpd.w. -
Enable the
Price,Qty, andDiscountcolumns in thettOlinebrowse.To do this, double-click on the browse, choose the Fields button in its property sheet, and double-click on each of the three fields. An ‘e' appears next to each field to indicate that it is now enabled for input, as shown:

You have to define a before-table for the
ttOlinetemp-table. Because this is a static temp-table, its before-table must be defined statically as well. -
Edit the include file
dsOrderTT.ito add theBEFORE-TABLEdefinition to the temp-table forOrderLines, as shown:. . . DEFINE TEMP-TABLE ttOLine BEFORE-TABLE ttOlineBefore . . .Using this definition, the AVM creates the companion temp-table
ttOlineBeforealong withttOline. The two temp-tables share the same scope. You can referencettOlineBeforein your procedure code just as you canttOline, but you cannot directly make any changes to its records. The before-table remains empty until you setTRACKING-CHANGESto true forttOlineand start making changes tottOlinerecords.You need to set the
TRACKING-CHANGESattribute to enable tracking of any updates to theOrderLines. -
In the
LEAVEtrigger for fieldiOrderNum, add a line to setTRACKING-CHANGESto true after receiving anOrderProDataSet back fromOrderMain.p. In addition, setTRACKING-CHANGESto false before requesting the ProDataSet, as shown:TEMP-TABLE ttOline:TRACKING-CHANGES = FALSE. DATASET dsOrder:GET-RELATION(1):QUERY:QUERY-CLOSE(). DATASET dsOrder:GET-RELATION(2):QUERY:QUERY-CLOSE(). DATASET dsOrder:EMPTY-DATASET. RUN OrderMain.p (INPUT iOrderNum, OUTPUT DATASET dsOrder BY-REFERENCE). TEMP-TABLE ttOline:TRACKING-CHANGES = TRUE. FIND FIRST ttOrder.When you set
TRACKING-CHANGESto true, you enable the user to change thePrice,Qty, andDiscountfields of one or morettOlinerecords and to have those changes recorded in the client window procedure. For each change, the AVM adds a record tottOlineBeforewith the record's values before it was first changed.To make sure that you can select and view one
Orderand then another without getting an error that says you are doing aFILLwhenTRACKING-CHANGESis true, you need to setTRACKING-CHANGESto false before making the call toOrderMain.p.You need to assign changes made to the browse columns.
-
Define this
ROW-LEAVEtrigger for theOlineBrowse, as shown:DO: DEFINE VARIABLE hCol AS HANDLE NO-UNDO. IF OlineBrowse:MODIFIED THEN ASSIGN INPUT BROWSE OlineBrowse {&ENABLED-FIELDS-IN-QUERY-OlineBrowse} /* Disable the Order Number until changes are saved. */ iOrderNum:SENSITIVE IN FRAME dsFrame = FALSE. END.In this trigger block, if the browse row has been modified, you assign the list of enabled columns. This is available as the preprocessor value
ENABLED-FIELDS-IN-QUERY-OlineBrowse, which allows you to make changes to the list of enabled columns without having to remember to go back to change a hard-coded field list in this trigger.Once the user has made any changes, you prevent them from switching
Ordersuntil the changes have been saved back to the database, by disabling theiOrderNumfield. -
The AVM does not automatically set the
MODIFIEDbrowse attribute to false when you switch rows, so you must define aVALUE-CHANGEDtrigger block for theOlineBrowse, as shown:DO: OlineBrowse:MODIFIED = FALSE. END.The
ROW-LEAVEevent fires before the browse switches rows, when you press the up or down arrow or select a different row with the mouse, for example. This lets you capture changes to the current row. TheVALUE-CHANGEDtrigger fires after the browse switches rows, so it would be too late to capture changes to the row you left. All you can do here is reset theMODIFIEDattribute in preparation for the next change.Start to build the trigger code that sends changes back to the database.
-
In the AppBuilder, drop a new button called
BtnSaveonto the window and label it Save Changes. -
To illustrate how
ROW-STATEand theBEFORE/AFTER-ROWIDattributes work, add this code to theCHOOSEtrigger for the button:FOR EACH ttOlineBefore: FIND ttOline WHERE ROWID(ttOline) = BUFFER ttOlineBefore:AFTER-ROWID. MESSAGE "Before ROW-STATE: " BUFFER ttOlineBefore:ROW-STATE " and Price: " ttOlineBefore.Price SKIP "After ROW-STATE: " BUFFER ttOline:ROW-STATE " and Price: " ttOline.Price. END.For each
OrderLinethat you change, there should be a record inttOlineBefore. That record points to its companion inttOlineusing theAFTER-ROWIDattribute. TheMESSAGEdisplays the value ofROW-STATEfor each record, along with thePricebefore and after the change. -
To try this out, run the window procedure, select an
Order, and modify one or two of thePricevalues of itsOrderLines. -
Choose the Save Changes button.
For each
OrderLineyou changed, you should see a message like the following for aPricechange from23.95to23.85:
This confirms that the
ROW-STATEattribute is always set for both the before-table record and the after-table record, so that you can query it starting at either table. TheROW-STATEvalue of2represents the literalROW-MODIFIED. In the case of a delete, of course, there will be a record with aROW-STATEof1(ROW-DELETED) only in the before-table, and no record in the after-table.The message also confirms that the before-table record holds the value of the fields before any changes were made, and the after-table holds the modified values.