Release 10.1A: OpenEdge Application Server:
Developing WebSpeed Applications

> ## Complex HTML mapping that includes a SmartDataObject

> Figure 2–7 shows the Web page generated by another sample WebSpeed application, `w-custdir.w`.

> Figure 2–7: Web page generated from w-custdir.w

> The Web page shown in Figure 2–7 interacts with the Customer table of the Sports2000 database like the other examples in this section. However, it also has the ability to add or change records in the table. Moreover, it uses a SmartDataObject to define its query logic. The following sections describe these features in more detail.

> ##### Creating a SmartDataObject

> SmartDataObjects provide query logic that is separate from the rest of your application. As separate modules, they can be used by multiple applications, can be refined at run time, and can be modified more easily than queries that are embedded within applications. Another advantage to SmartDataObjects is that they can be used on an AppServer™ for multi-tier deployment. See OpenEdge Application Server: Developing AppServer Applications for more information.

> SmartDataObjects can easily be created in the AppBuilder. The SmartDataObject associated with `w-custdir.w` is called `dcustomer.w`.

> | To create SmartDataObjects in the AppBuilder:

> 1. Choose File New from the AppBuilder main menu.

> The New dialog box appears:

> 2. Select SmartDataObject from the list of SmartObjects.

> Note that AppBuilder must be connected to a database in order to create a SmartDataObject. The procedures for starting and connecting to a database are described in OpenEdge Getting Started: WebSpeed Essentials .

> 3. Choose Next on the SmartDataObject Wizard, then choose Define Query from page 2 of the wizard.

> 4. In the Query Builder:

> 1. Add the Customer table to the Select Tables list.
> 2. Select the Sort button.
> 3. Add Name to the Selected Fields list.
> 5. Go to the next dialog box in the wizard (page 4) and choose Add Fields.

> 6. Choose Add and add all of the available fields to the Selected Fields list.

> 7. Go to the final page of the wizard and choose Finish.

> You will see a window labeled Untitled, which represents the SmartDataObject you just created. You can save it as `dcustomer.w` from the File menu of the AppBuilder.

> When you save a SmartDataObject, you create a number of files: .w, .r, _cl.w, _cl.r, and .i. For more information about the function of these files, or for more information about SmartDataObjects in general, see OpenEdge Development: ADM and SmartObjects and OpenEdge Development: ADM Reference .

> For more information about creating SmartDataObjects with the AppBuilder, see the OpenEdge Development: AppBuilder .

> ##### Mapping with a SmartDataObject

> You can specify `dcustomer.w` as the data source when you use the HTML Mapping Wizard to map an HTML file like `w-custdir.htm`:

> w-custdir.htm
>     <html>
>     <head>
>     <title>Sample of Using HTML Mapping with an SDO</title>
>     </head>
>     <h3><font color="#000000">Customer Directory</font></h3>
>     <form ACTION="w-custdir.w" METHOD="POST">
>     <input type="hidden" name="cusrowid" >
>     <input type="hidden" name="AddMode" >
>     <pre>
>     <input NAME="SearchName" SIZE="20">
>     <input TYPE="submit" NAME="requestedAction" VALUE="Search for Name">
>     Name :  <input NAME="Name" SIZE="34">
>     Address: <input NAME="Address" SIZE="34">
>             <input NAME="City" SIZE="12">
>             <input NAME="State" SIZE="20">
>             <input NAME="PostalCode" SIZE="10">
>     Phone:  <input NAME="Phone" SIZE="20">
>     Email:  <input NAME="EmailAddress" SIZE="20">
>     Fax:    <input NAME="Fax" SIZE="20">
>     Sales Rep:<input NAME="SalesRep" SIZE="5">
>     <input TYPE="submit" NAME="requestedAction" VALUE="First">
>     <input TYPE="submit" NAME="requestedAction" VALUE="Next">
>     <input TYPE="submit" NAME="requestedAction" VALUE="Prev">
>     <input TYPE="submit" NAME="requestedAction" VALUE="Last">
>     <input TYPE="submit" NAME="requestedAction" VALUE="Save">
>     <input TYPE="submit" NAME="requestedAction" VALUE="Add">
>     <input TYPE="submit" NAME="requestedAction" VALUE="Delete">
>     <input TYPE="submit" NAME="requestedAction" VALUE="Reset">
>     <input TYPE="submit" NAME="requestedAction" VALUE="Cancel">
>     </pre>
>     </form>
>     </body>
>     </html>

> You can use the HTML Mapping Wizard’s Automap feature to map the fields referenced in `w-custdir.htm` to the database fields referenced in `dcustomer.w`. Note that all the fields will map except the hidden fields and the `SearchName` field (shown in bold). These fields are used to pass information to the WebSpeed agent and do not reference fields in the database.

> The hidden field, `cusrowid`, holds a value that identifies the current record that is displayed on the Web page. It establishes a context for the WebSpeed agent when the next request is submitted. The other hidden field, `AddMode`, holds a value that tells the WebSpeed agent if a new record is to be added or not added when the next request is submitted. The code that utilizes these hidden fields is explained in the following section.

> ##### Adding code

> After the HTML Mapping Wizard completes, you will see a tree view of an untitled Web object, which is similar to Figure 2–8.

> Figure 2–8: Tree view of an untitled HTML-mapping object

> From the Code Sections branch of the tree view, you can add all the code that is necessary to complete `w-custdir.w`. With Code Sections selected, choose the Edit Code button from the AppBuilder Tool Bar to start the Section Editor. The Section Editor allows you to add new procedures, to modify default procedures, and to invoke and override super procedures. For more information, see the OpenEdge Development: AppBuilder .

> | To complete the Web object:

> 1. Create a trigger that responds to the value of cusrowid.

> In the trigger, the value of `cusrowid` is passed to the `setCurrentRowids` procedure. Recall that the value of `cusrowid` is stored in a hidden field and is set in a prior WebSpeed transaction. The trigger essentially tells the WebSpeed agent which row in the table to refer to. In other words, the trigger establishes a context for the WebSpeed agent by passing information about a previous transaction.

> In the example Web object, the trigger is called `Web.input` and the code looks similar to the following:

> Web.input
>     /*---------------------------------------------------------------------
>       Purpose:     Assigns form field data value to frame screen value.
>       Parameters:  p-field-value
>       Notes:       This input trigger of the hidden field cusrowid sets the
>                    current row to the one in the hidden field to set the
>                    context in preparation for further processing.
>     ---------------------------------------------------------------------*/
>       DEFINE INPUT PARAMETER p-field-value AS CHARACTER NO-UNDO.

>       DO WITH FRAME {&FRAME-NAME}:
>         setCurrentRowids (p-field-value).
>       END.

>     END PROCEDURE.

> 2. Create a procedure that responds to the `AddMode` flag.

> In the example Web object, the procedure is called `inputFields`, and the code looks similar to the following:

> inputFields
>     /*---------------------------------------------------------------------
>       Purpose:     Super Override
>       Parameters:
>       Notes:  After standard behavior for this procedure, this procedure
>       override looks at a hidden field called AddMode, and sets a flag
>       indicating that this record is new, and must be created in the
>       database before the fields are assigned.  The AddMode flag is then
>       turned off in preparation for sending the next page.
>     ---------------------------------------------------------------------*/
>      RUN SUPER.

>      IF  ab_unmap.AddMode:screen-value in frame {&FRAME-NAME} = "YES" THEN
>      DO:
>       PleaseAdd = TRUE.
>       setAddMode (TRUE).
>      END.
>      IF  ab_unmap.AddMode:screen-value in frame {&FRAME-NAME} = "NO" THEN
>      DO:
>        PleaseAdd = FALSE.
>        setAddMode (FALSE).
>      END.
>      ab_unmap.AddMode:screen-value in frame {&FRAME-NAME} = "No".

>     END PROCEDURE.

> As noted in the comment, this procedure is actually an override to the `inputFields` super procedure. This override supplements the standard behavior of `inputFields` by allowing it to react to the value of the `AddMode` flag in the hidden field. This code allows the Web object to add a new record to the database.

> 3. Create a procedure that manages the unmapped fields.

> In the example Web object, the procedure is called `outputFields`, and the code looks similar to the following:

> outputFields
>     /*---------------------------------------------------------------------
>       Purpose:     Super Override
>       Parameters:
>       Notes: This outputs the current record to the hidden field cusrowid
>       before standard behavior for this procedure and outputs the AddMode
>       hidden field.
>     ---------------------------------------------------------------------*/
>     IF getUpdateMode() = "Add" THEN
>         ab_unmap.AddMode:screen-value in frame {&FRAME-NAME} = "YES".
>     ELSE
>         ab_unmap.AddMode:screen-value in frame {&FRAME-NAME} = "NO".

>     ab_unmap.cusrowid:screen-value in frame {&FRAME-NAME} = getRowids().

>     RUN SUPER.

>     END PROCEDURE.

> As noted in the comment, this procedure is actually an override to the `outputFields` super procedure. Its purpose is to identify the correct row for the next transaction. This override sets the value of `ab_unmap.custrowid` to the rowid of the current record. The value of `ab_unmap.custrowid` is set before running `outputFields`.

> The `ab_unmap` temporary table holds the values of the fields that are unmapped. In this example, the unmapped fields are `cusrowid`, `SearchName`, and `AddMode`.

> Note: The AppBuilder online help contains reference pages that describe the syntax and behavior `inputFields`, `outputFields`, and all other super procedures that apply to WebSpeed. For more information about using super procedures, see the OpenEdge Development: ADM and SmartObjects and the OpenEdge Development: ADM Reference .

> 4. Modify `process-web-request` so that the Web object responds to button events.

> The button events are handled in a case statement, as shown in the following segment:

> process-web-request
>       IF REQUEST_METHOD = "POST":U THEN DO:
>         RUN inputFields.
>         RUN findRecords.
>         CASE get-field ("requestedAction"):
>             WHEN "First" THEN
>               RUN fetchFirst.
>             WHEN "Next" THEN
>               RUN fetchNext.
>             WHEN "Prev" THEN
>               RUN fetchPrev.
>             WHEN "Last" THEN
>               RUN fetchLast.
>             WHEN "Search for Name" THEN DO:
>               addSearchCriteria(’name’,get-value(’searchname’)).
>               RUN findRecords.
>             END.
>             /* Maintenance action selected  */
>             WHEN "Save" THEN DO:
>                 IF getUpdateMode () <> "add" THEN
>               RUN fetchCurrent.
>               RUN assignFields.
>               setAddMode (FALSE).
>               setUpdateMode ("").
>             END.
>             WHEN "Delete" THEN DO:
>               RUN fetchCurrent.
>               deleteRow().
>             END.
>             WHEN "Reset" THEN DO:
>               RUN fetchCurrent.
>             END.
>             WHEN "Cancel" THEN DO:
>               RUN fetchCurrent.
>               setUpdateMode ("").
>             END.
>             WHEN "Add" THEN DO:
>               RUN fetchCurrent.
>               setUpdateMode ("Add").
>             END.
>         END CASE.

Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095