Skip to content

Changes in Retain and Retain-All

The behavior of the Retain and Retain-All attributes has been improved in DDOs. They now work as follows:

  • If the DD_Retain attribute option is set for a field, the value of that field will be retained during a DDO clear operation. It will be cleared during a DDO clear_all operation.

  • Retains are applied to the DDO receiving the clear message and all parent DDOs. It is not applied to child DDOs (you would not want it applied to child DDOs).

  • If the DD_RetainAll attribute option is set for a field, the value of the field is always retained. Retain-All is applied to all DDOs. It is not expected that the DD_RetainAll option will be used often.

Important: It is really expected that Retain will be applied at the DD object level and not as part of the class definition. The choice to retain or not retain a value is not something that can usually be applied to all objects in all views using a particular DD class. Instead, retains should be applied based on the data entry requirements of a particular view. This means that the DD_Retain field option in Database Builder will rarely be checked. Instead, you should set retained fields directly within the DD object. You can do this using the new 8.1 messages set file_field_option, set file_field_option_clear, and set file_field_option_toggle.

The following lines inside of a DD object will set retain fields for Customer.State and Customer.Zip_Code:

Set file_field_option file_field Customer.State to DD_Retain
Set file_field_option file_field Customer.Zip_Code to DD_Retain

You can clear or toggle the retain option as follows:

Set file_field_option_clear file_field Customer.State to DD_Retain
// make sure retain is cleared
Set file_field_option_toggle file_field Customer.State to DD_Retain
// toggle the current retain state

Changing Retains Dynamically

The ability to clear and toggle fields is useful because the retain attribute (and in 8.1 all DD option attributes) can be changed dynamically. You could create views where the person doing the data entry can decide which fields in their view to retain. The following sample code could be added to your view object and would let the user toggle the retain state of any field in the view:

// all objects in this view will send ToggleRetain when Ctrl/F4 is pressed.
On_key key_ctrl+key_f4 send ToggleRetain
// When sent from a Ctrl/F4, the message will delegate here to the view
// because ToggleRetain is not directly understood by the other objects
Procedure ToggleRetain handle hoDEO hoServer integer iFile iField
    // we want to react to the focus object. The object where ctrl/f4 was pressed
    Get Focus to hoDEO
    // non DEOs will understand this message via delegation...see below
    Get Data_file of hoDEO to iFile
    If (iFile = 0) Procedure_return // probably not a DEO that has the focus
    Get Server of hoDEO to hoServer
    If (hoServer) begin
        Get Data_field of hoDEO to iField
        set File_field_Option_Toggle of hoServer iFile iField to DD_RETAIN
    end
End_procedure

// this augmentation was created to allow non-DEOs to respond to ctrl/f4
// without an error message. Non-DEOs will delegate this message to
// here, return 0 and do nothing... look at toggle retain
Function Data_file returns integer
    Function_return 0
End_function

Retains and Setting Default Field Values

Database Builder allows you to create default values for fields. For example, the default value for customer.state is "FL". These defaults are applied after field values are retained and consequently they will overwrite the value of the retained data. So, normally you would not use retains and defaults on the same field.

You could use both retains and defaults together to create intelligent defaults. Remember that default values are set within the procedure field_defaults. You can augment the field_defaults method to create custom default values. During that process, you can check to see if a value has been retained and respond however you want.

The following code added to the customer DDO would retain the current state value if it exists. If the state is blank or if the state is "CA" (maybe we just don’t like California), the default "FL" will get used:

Set file_field_option file_field Customer.State to DD_Retain // retain customer.state

Procedure Field_defaults string sState
    Forward Send Field_Defaults
    // get current state value, could be cleared or a retained value
    Get File_Field_Current_Value file_field customer.state to sState
    // if state is cleared or it is CA, set a default of FL
    if (sState = "" or sState = "CA") Set File_Field_changed_Value file_field customer.state to "FL"
End_Procedure

The Field_defaults method should only be used to set default values for fields from its own DDO. It should not try to change the value of parent or child DDOs and it should not try to perform additional DDO operations (like an autofind).

Retains with Parent (Foreign) Fields

We expect you to assign Retains at the object level. Therefore it is up to you to decide if it makes sense to retain fields from parent DDOs. Normally a parent DDO requires an autofind. Therefore retaining any field other than the key autofind field probably makes little sense. Retaining the key field(s) of a parent file may make a great deal of sense.

If you retain a key parent field, the data will be retained but the record will not be found automatically. This is intentional and it gives you two choices. You can either let the autofind occur when you navigate out of the field or you can force an autofind as part of the clear operation. We will show you examples of both.

Add the following line of code to the OrderHea DDO in the order entry view and compile and run the view:

set file_field_option file_field customer.Customer_number to DD_Retain

When you clear the order view, the customer ID will be retained but the rest of the customer data is blank. When you navigate out of the customer entry field, an autofind will occur. This is one way to use retains with parents. It allows the user to select a different customer ID before performing the autofind.

Now try adding the following code to the same OrderHea DDO in the order view:

set file_field_option file_field customer.Customer_number to DD_Retain
// augment clear so that it performs an autofind for the customer. The retained
// data will be used to perform this autofind
procedure clear
    forward send clear
    send File_field_Default_Autofind file_field customer.Customer_number
end_procedure

When you run this sample, you will see that the entire customer appears to be retained. Actually, the key field is retained and then after the clear, an autofind is performed. The new DDO message File_field_Default_Autofind is used here to perform the autofind in "default" mode (the DDO's changed state is not set by the find). Note that you should not try doing an autofind as part of the field_defaults process. The Field_Defaults method can only be used to set defaults for the fields that belong to its DDO and you should never perform database activity (and particularly DDO database activity) within this method.