Extend the sample window to filter dynamically
- Last Updated: May 7, 2024
- 3 minute read
- OpenEdge
- Version 12.8
- Documentation
You already extended the h-CustOrderWin4.w version of the sample window
once in Use Queries to filter the records for a particular state. In that version of the procedure, the
LEAVE trigger on the New State field reopens
the Customer query based on the state abbreviation entered:
|
A static OPEN QUERY statement suffices, because the
WHERE clause is known. The only variable is the state abbreviation,
and the procedure can plug that into the OPEN QUERY statement.
You should use the dynamic QUERY-PREPARE and QUERY-OPEN
methods when your procedure needs more flexibility than this. To show how this can work,
you can extend the filtering to apply to every field in the
Customer table that the window displays. You can change the
procedure to let the user filter the Customers based on a value
you enter in any of the Customer fields. You can then add a
filter button to the window that blanks out the Customer fields
and enables them. When the user enters a value in any one of the fields, the code
re-prepares and reopens the query to filter on the value for that field.
To make these changes:
- Open h-CustOrderWin1.w and save it as h-CustOrderWin8.w.
- Disable all the Customer fields that are
displayed.
Remember that you can select the fields, open the Properties Window, and set Enabled to false for all of them at once. Making them initially disabled allows you to enable them for input only when you want to filter on a value in a field.
- Remove the phrases from the query that filter on
State = “NH”and sort by City.Because the user will be filtering on any field, it makes sense to remove the initial filtering and sorting that this version of the procedure from Introduction to the OpenEdge AppBuilder. If you double-click on the frame, its property sheet opens where you can access the Query Builder to make the changes. Select the Where and Sort radio set options in turn to make the changes.
- Drop a button onto the frame next to the navigation buttons. Name it btnFilter and give it a Label of Filter.
- Define a
CHOOSEtrigger for the Filter button. The trigger code needs to blank out all the Customer fields and enable them for input.What code can you write to do this? The quickest way is to set the
SCREEN-VALUEof each field to "" and to set theSENSITIVEattribute to YES. (Remember that theSCREEN-VALUEis the value displayed in the frame and thatSENSITIVEis the attribute name for theEnabledproperty of an object.):ASSIGN Customer.CustNum:SCREEN-VALUE = "" Customer.Name:SCREEN-VALUE = "" Customer.Address:SCREEN-VALUE = "" Customer.City:SCREEN-VALUE = "" Customer.State:SCREEN-VALUE = "" Customer.CustNum:SENSITIVE = YES Customer.Name:SENSITIVE = YES Customer.Address:SENSITIVE = YES Customer.City:SENSITIVE = YES Customer.State:SENSITIVE = YES.This code certainly works, but does it make you a little uncomfortable? What happens if you later add a field to the frame or remove one? Then you have a maintenance problem on your hands. Try identifying the fill-ins dynamically instead, using what you learned in the previous section.
- Define a variable scoped to the procedure to hold the field handles in the
Definitions section:
/* Local Variable Definitions --- */ DEFINE VARIABLE cFillIns AS CHARACTER NO-UNDO. - Add code so that the
CHOOSEtrigger builds up a list of all the handles of the objects in the frame that are fill-in fields, if the list has not already been built:DO: DEFINE VARIABLE hContainer AS HANDLE NO-UNDO. DEFINE VARIABLE hField AS HANDLE NO-UNDO. DEFINE VARIABLE iField AS INTEGER NO-UNDO. IF cFillIns = "" THEN DO: /* Identify all the fill-ins so they can be enabled, disabled, and cleared. */ ASSIGN hContainer = FRAME CustQuery:HANDLE hContainer = hContainer:FIRST-CHILD. /* The field group */ hField = hContainer:FIRST-CHILD. DO WHILE VALID-HANDLE(hField): IF hField:TYPE = "Fill-In" THEN cFillIns = cFillIns + (IF cFillIns = "" THEN "" ELSE ",") + STRING(hField). hField = hField:NEXT-SIBLING. END. END. - Whether the field list has already been built or not, the procedure needs to walk
through those fields and blank them and disable them:
DO iField = 1 TO NUM-ENTRIES(cFillIns): ASSIGN hField = WIDGET-HANDLE(ENTRY(iField, cFillins)) hField:SCREEN-VALUE = "" hField:SENSITIVE = YES. END.Now if you later change the fields on the screen, you do not have to change this code. That is part of the value of dynamic programming!