Consultor Eletrônico



Kbase 15487: Using Attribute List to Pass Values Between V8 SmartObjects
Autor   Progress Software Corporation - Progress
Acesso   Público
Publicação   15/10/2008
Status: Verified

GOAL:

How to make a SmartObject react to specific values passed from another SmartObject using attribute list values.

FACT(s) (Environment):

Progress 8.x

FIX:

There are many cases when one SmartObject requires information from another SmartObject.  It is important to encapsulate each Object's functionality while accomplishing the communication of needed values.  Encapsulation allows maximum code reusability.  Thus, there are several methods of exchanging information between SmartObjects.  One way is to use an attribute.

An example of exchanging information would be, using the value of a fill-in object to re-open a SmartQuery linked to a SmartViewer.  For instance, you could allow the user to select a subset of records by entering the beginning characters of customer name.  The user's entered value would be picked up by the SmartQuery and used to re-open the query, updating the SmartViewer and associated SmartPanel.

With Version 8, there are several method procedures which operate on attributes for SmartObjects.  These methods allow you to access existing attributes and reference new ones.

For simplicity, let's say the fill-in is part of the SmartViewer. (This may not be the best interface design, but will serve as an example.)  When the user enters a value in this fill-in object, we want to re-open a SmartQuery for customers whose name begins with the entered value, and display those records in the SmartViewer, using a SmartPanel to navigate the results list from the SmartQuery.

The first step is to create a freeform SmartQuery from the UIB. The freeform query is necessary because we will be using a local variable in the query and the UIB's query building doesn't allow this.  In the freeform query, you'll need to RUN GET-ATTRIBUTE to retrieve the information placed in a new attribute which we'll call key-value for this example.  Later you'll see how the information
is placed in key-value -- for now, just set up the query.  The GET-ATTRIBUTE procedure sets RETURN-VALUE to the current value of the specified attribute.

All attributes are held as character values, so you'll need to have a character variable to hold the attribute value.  The format will depend on the length of the information being passed -- this example allows up to twenty characters.

In order to keep the SmartQuery and the other SmartObjects in synch, you'll have to use ADM messaging to "notify" the other objects that the query has been re-opened.  This example sends the GET-FIRST message to all associated SmartObjects.

/* The following code is from the freeform query code section.
This can be seen in the OPEN_QUERY trigger of the SmartQuery */

DEFINE VARIABLE cMyString AS CHARACTER NO-UNDO FORMAT "X(20)".
  
RUN GET-ATTRIBUTE ("key-value":U).

ASSIGN cMyString = RETURN-VALUE.

  IF cMyString <> "" THEN
DO:
   OPEN QUERY Query-Main FOR EACH Customer NO-LOCK
       WHERE Customer.Name BEGINS cMyString.
    RUN NOTIFY ('GET-FIRST':U).
END.

Now, for the SmartViewer, there's a little more work to be done to set up the sending side.  This example uses the ADM-BROKER-HDL procedures to obtain handles to other SmartObjects.  Each SmartObject must be independent of others.  You won't be able to compile a SmartObject master with any reference to other SmartObjects since they aren't "known" at design time.  You have to retrieve them indirectly through the ADM Broker.  This example runs GET-LINK-HANDLE to retrieve the TABLEIO-SOURCE for the Viewer and saves the handle in a variable called h-updpanel.  It also disables the Panel while the user is updating the fill-in data.  This maintains a consistent appearance depending on the results of the re-opened query.

When the user is done entering the beginning value for the query, the value is verified to ensure there's at least one record that will satisfy the query.  Then, the query's handle is retrieved with another call to GET-LINK-HANDLE looking for RECORD-SOURCE.  (Note that *all* record sources for the current object .will be returned.  You have to know whether you're likely to have more than one active record source for the Viewer and plan accordingly if you do.  This example assumes there's only one.)  The query handle is stored in h-query.

Finally, the new attribute value is established in a variable called alist and that variable is then used in the call to SET-ATTRIBUTE-LIST with h-query as the target.  The last step is to instruct the SmartQuery to execute its open-query procedure. DISPATCH is used because we only want to re-open this specific query.

Here's how the final code sections look in the SmartViewer:

/* NOTE:  The extracted code which follows should NOT be edited
into the .w.  You should use the UIB to modify the Viewer and
query.  This example is included only to demonstrate what needs
to be added to various code sections */

/* Code added in the SMARTVIEWER */

/*...*/
/* Local Variable Definitions ---                                       */

DEFINE VARIABLE h-updpanel AS HANDLE NO-UNDO.
   DEFINE VARIABLE h-query AS HANDLE NO-UNDO.
   DEFINE VARIABLE c AS CHARACTER NO-UNDO.
   DEFINE VARIABLE alist AS CHARACTER NO-UNDO.

/*...*/
/* Control Triggers */

ON ENTRY OF FILL-IN-1 IN FRAME F-Main /* Fill 1 */
DO:
      /* Get handle of table-io link source */
   RUN get-link-handle IN adm-broker-hdl (this-procedure, 'tableio-source':U, output c).  
  ASSIGN h-updpanel = WIDGET-HANDLE(c).

      /* disable panel while fill-in is processed */
  RUN dispatch IN h-updpanel ('adm-disable').
END.

ON LEAVE OF FILL-IN-1 IN FRAME F-Main /* Fill 1 */
DO:
IF fill-in-1:SCREEN-VALUE <> '' THEN
DO:
   /* re-enable panel buttons now that we're in the LEAVE trigger */
ASSIGN fill-in-1.
 RUN dispatch IN h-updpanel ('adm-enable').

FIND FIRST customer WHERE customer.name BEGINS fill-in-1 NO-LOCK NO-ERROR.
IF NOT AVAILABLE(customer) THEN
DO:
   MESSAGE "no records exist with name beginning " +
            fill-in-1 VIEW-AS ALERT-BOX.
    RETURN NO-APPLY.
END.

     /* Get the query record source handle to pass the re-open value via attribute */
RUN get-link-handle IN adm-broker-hdl (this-procedure, 'record-source':U, output c).

  ASSIGN h-query = WIDGET-HANDLE(c)
  alist = "key-value = ":U + fill-in-1.


RUN set-attribute-list IN h-query (alist).
   RUN dispatch IN h-query ('open-query':U).
  END.
END.

ON GO OF FILL-IN-1 IN FRAME F-Main /* Fill 1 */
DO:
APPLY "leave" TO SELF.
END.

ON RETURN OF FILL-IN-1 IN FRAME F-Main /* Fill 1 */
DO:
APPLY "leave" TO SELF.
END.
.