In this section, you add a dynamic menu to the test window. The menu displays all SalesReps and lets the user filter the list of Customers by a selected SalesRep. This example demonstrates one typical use of dynamic menus—to create a list of menu items that are data-driven. In other cases, a list of dynamic menu items might be based on currently available windows or other elements of an application that can vary at run time.

To add a dynamic menu bar to the h-CustOrderWin7.w procedure:

  1. Add a new fill-in field to the window to display the selected SalesRep. Name it cSalesRep.
  2. Create a new internal procedure called createMenu. The procedure needs handle variables for the menu bar, its submenu, and one handle for all the menu items you create:
    DEFINE VARIABLE hMenu AS HANDLE NO-UNDO.
    DEFINE VARIABLE hSubMenu AS HANDLE NO-UNDO.
    DEFINE VARIABLE hMenuItem AS HANDLE NO-UNDO.
  3. Create the menu bar and its submenu:
    CREATE MENU hMenu.
    CREATE SUB-MENU hSubMenu
    ASSIGN PARENT = hMenu
      LABEL = "SalesReps".
  4. Create the list of SalesReps as menu items:
    FOR EACH SalesRep:
      CREATE MENU-ITEM hMenuItem
      ASSIGN PARENT = hSubMenu
        LABEL = SalesRep.SalesRep + " " + SalesRep.RepName
        TRIGGERS:
          ON CHOOSE PERSISTENT RUN filterCust IN THIS-PROCEDURE.
        END TRIGGERS.
    END.

    Each one is parented to the submenu. You can reuse the same object handle for each one because you do not need to reference those objects individually. Each menu item has the SalesRep initials followed by the SalesRep’s full name as its label.

    When the user chooses one of these items, you want to reopen the Customer query for just Customers of that SalesRep. Remember that when you define a trigger on an object inside an internal procedure or another trigger block, the trigger definition does not persist beyond the end of that procedure or block. Therefore, you have to use the special PERSISTENT RUN statement to tell the AVM to run a separate procedure when the event occurs. You write this filterCust procedure in a moment.

  5. Add a couple of special menu items to the end of the list. Create a RULE to separate the SalesReps from the final menu item:
    CREATE MENU-ITEM hMenuItem
      ASSIGN SUBTYPE = "RULE"
        PARENT = hSubMenu.
  6. Add a menu item that closes the window and its procedure:
    CREATE MENU-ITEM hMenuItem
      ASSIGN PARENT = hSubMenu
        LABEL = "E&xit"
        TRIGGERS:
          ON CHOOSE PERSISTENT RUN leaveProc IN THIS-PROCEDURE.
        END TRIGGERS.

    Once again, the trigger code has to be in a separate procedure.

  7. Parent the menu bar to the window:
    CURRENT-WINDOW:MENUBAR = hMenu.
  8. Create the filterCust procedure for the SalesRep items:
    /*---------------------------------------------------------------------
    Procedure: filterCust
    Purpose: Filters customers by the selected SalesRep menu item.
    ---------------------------------------------------------------------*/
    OPEN QUERY CustQuery FOR EACH Customer
      WHERE Customer.SalesRep = ENTRY (1, SELF:LABEL, " ").
    cSalesRep:SCREEN-VALUE IN FRAME CustQuery = SELF:LABEL.
    APPLY "CHOOSE" TO BtnFirst IN FRAME CustQuery.
    END PROCEDURE.

    This code reopens the Customer query for just those Customers whose initials match the first part of the menu item label. Remember that the built-in handle SELF always evaluates to the object handle that triggered the event.

    The procedure displays the selected SalesRep in the new fill-in field, and then resyncs the display to the first record in the new query by programmatically clicking the First button.

  9. Define the internal procedure leaveProc to handle the Exit button:
    /*---------------------------------------------------------------------
    Procedure: leaveProc
    Purpose: Handles the Exit menu item
    ---------------------------------------------------------------------*/
    APPLY "CLOSE" TO THIS-PROCEDURE.
    END PROCEDURE.

    This code simply invokes the CLOSE event already defined as a standard part of the AppBuilder-generated code for the window.

  10. Add a statement to the procedure’s main block to run createMenu:
    .
    ..
    RUN enable_UI.
    RUN createMenu.
    RUN h-StartSuper.p("h-dynsuper.p").
    RUN changeFields.
    ...
  11. Run the procedure again. Now you can drop down a list of all the SalesReps:
  12. Select one. Now Customers are selected for that SalesRep only: