Can't find what you are looking for? Try these pages!


DataFlex Reports and The Web (I)

April 15,2013
By Vincent Oorsprong

At the just ended Synergy 2013 conference held in Nashville, Tennessee we have shown how easy it will be to make Web Based Applications using the DataFlex Web Application Framework. One of the parts of a Web Application will be reporting. Data Access advises two reporting solutions; Dynamic AI and DataFlex Reports. During the Synergy sessions (symposium and trainings) demonstrations were given how relative easy it is to integrate the two reporting solutions in a Web Application made with the DataFlex Web Application Framework. To complete this we have created two demonstration websites where the power of Dynamic AI and DataFlex Reports as reporting solution are shown in real time. You can feel the speed, the output solutions and in this blog and the next blogs I will show you how what is behind the website, how it is made.

Before continue reading this blog I would advise you to visit the demonstration websites. You can visit the Dynamic AI demo website to feel the power of Dynamic AI and visit the Dataflex Reports demo site to see it in action.

The Start Page

The links above that go to the demo websites brings open a start page named "The Solution". Opening this page is controlled by setting the phoDefaultView property to this cWebView object. This page is a cWebView classed based component containing two panel (cWebPanel) objects. The panel on the left hand side is set to a width and can be resized by the visitor grabbing the splitter between the two panels. The splitter is turned on by setting the pbResizable property of the left panel to true. The panel on the right hand side does not have a width and the size is determined by the size of your browser. The panel on the left contains a treeview control (cWebTreeView) for navigation purposes. The contents are read from a DataFlex embedded database table. This allows us to change the contents without recompilation of the application. The first level of the tree is automatically expanded. Clicking on a node executes a find request at the server and results in showing the documentation text on the right panel which contains a cWebHTMLBox control. The text is stored as HTML in a TEXT based column in the documentation table. The text contains special instructions that allows the server to open an integration web view when the user clicks on a link.
While the Dynamic AI and DataFlex Reports demo websites are similar they will not be identical, they are two different report solutions. The next part of this blog and the next blogs are written from what you see on the DataFlex Reports live demo website.

Ok, enough said, let’s look at some code that was used to fill the page.

In the OnLoad event of the cWebTreeView control the data is loaded. This is automatic and the events sends a message OnLoadChildNodes to get its data. In the treeview coded here the data is read from a table named Documentation. The code for this is:

Function OnLoadChildNodes String sId String sValue Integer iLevel Returns tWebTreeItem[]
    tWebTreeItem[] TreeItems
    Get CollectTreeData sId to TreeItems
    Function_Return TreeItems
Function AppendTreeData tWebTreeItem[] ByRef DestinationTreeItems tWebTreeItem[] ByRef SourceTreeItems Returns Integer
    Integer iElements iElement iDestinationElement
    Move (SizeOfArray (DestinationTreeItems)) to iDestinationElement
    Move (SizeOfArray (SourceTreeItems)) to iElements
    For iElement from 0 to (iElements - 1)
        Move SourceTreeItems[iElement] to DestinationTreeItems[iDestinationElement]
        Increment iDestinationElement
    Function_Return iElements
Function CollectTreeData String sId Returns tWebTreeItem[]
    tWebTreeItem[] TreeItems ChildTreeItems
    Integer iElement iAddedItems iSet
    RowID riDocumentation
    Move (sId + 1) to iSet
    Constraint_Set iSet Clear
    Constrain Documentation.ParentID eq sId
    Constrained_Find First Documentation by 1
    While (Found)
        Move Documentation.ID to TreeItems[iElement].sId
        Move Documentation.ParentID to TreeItems[iElement].sParentId
        Move (Trim (Documentation.Name)) to TreeItems[iElement].sName
        Move Documentation.LoadChildren to TreeItems[iElement].bLoadChildren
        Move Documentation.Folder to TreeItems[iElement].bFolder
        Move Documentation.Expanded to TreeItems[iElement].bExpanded
        Move Documentation.Icon to TreeItems[iElement].sIcon
        Move (Trim (Documentation.CSSClass)) to TreeItems[iElement].sCSSClass
        Move (Trim (Documentation.AltText)) to TreeItems[iElement].sAltText
        Increment iElement
        If (Documentation.Expanded) Begin
            Move (GetRowID (Documentation.File_Number)) to riDocumentation
            Get CollectTreeData Documentation.ID to ChildTreeItems
            Get AppendTreeData (&TreeItems) (&ChildTreeItems) to iAddedItems
            Move (iElement + iAddedItems) to iElement
            Move (FindByRowID (Documentation.File_Number, riDocumentation)) to Found
        Constraint_Set iSet
        Constrained_Find Next
    Constraint_Set iSet Delete
    Function_Return TreeItems

So the OnLoadChildNodes event sends a message to read the data from the table. If none of the rows does have the Expanded column set to true the routine would only load the data at the first level and the user needs to expand each tree item.
To ensure the first item is selected the OnLoad event is augmented to Select the item that corresponds with the first row in the table.

Procedure OnLoad
    Forward Send OnLoad
    Clear Documentation
    Find Gt Documentation by 1
    Send Select Documentation.ID

The table layout is simple but complex as it uses a relationship to itself by using an ALIAS table and allowing NULL parent support. The table structure is:

--- --------------- ---- ----- ----- --
1 ID NUM 4.0 1 1
2 ParentID NUM 4.0 3
3 Name ASC 255 5
4 LoadChildren NUM 2.0 260
5 Folder NUM 2.0 261
6 Icon ASC 255 262
7 CSSClass ASC 100 517
8 AltText ASC 150 617
9 Value TEX 14752 767
10 Expanded NUM 2.0 15519
11 ViewName ASC 250 15520 2

The column ParentID links to the ALIAS table for Documentation from within the DataDictionary object that is used when we enter or alter the documentation. As you can see above the DataDictionary object is not used for reading the data into the treeview. While it could have been used there is no need to do so. The DataDictionary class that is used for DDOs when entering documentation is as follows:

Use DataDict.pkg
Open Documentation
Open DocumentationParent
Register_Object oDocumentationWebLookup
Class cDocumentationDataDictionary is a DataDictionary
    Procedure Construct_Object
        Forward Send Construct_Object
        Set Main_File to Documentation.File_Number
        Set Add_Server_File to DocumentationParent.File_Number
        Set ParentNullAllowed DocumentationParent.File_Number to True
        Set Foreign_Field_Option DD_KEYFIELD DD_NOPUT to True
        Set Foreign_Field_Option DD_KEYFIELD DD_FINDREQ to True
        Set Foreign_Field_Option DD_INDEXFIELD DD_NOPUT to True
        Set Foreign_Field_Option DD_DEFAULT DD_DISPLAYONLY to True
        Set Field_WebPrompt_Object Field Documentation.ID to oDocumentationWebLookup
        Set Field_Option Field Documentation.ID DD_AUTOFIND to True
        Set Field_Class_Name Field Documentation.LoadChildren to "Checkbox"
        Set Field_Class_Name Field Documentation.Folder to "Checkbox"
        Set pbUseDDRelates to True
        Set Field_Related_FileField Field Documentation.ParentID to File_Field DocumentationParent.ID
#IFDEF Is$WebApp
Use Lookups\DocumentationWebLookup.wo

Clicking a node in the treeview sends the OnSelect event to the server. In the OnSelect the row that is linked to the tree item is found and its documentation data is send to the cWebHtmlBox control via an UpdateHtml message.

Procedure OnSelect String sId String sValue Integer iLevel
    Forward Send OnSelect sId sValue iLevel
    Clear Documentation
    Move sId to Documentation.ID
    Find Eq Documentation.ID
    Move (Trim (Documentation.Value)) to sValue
    If (sValue = "") Begin
        Move " " to sValue
    Send UpdateHtml of oWebDocumentationBox sValue


The panel on the right contains a cWebHTMLBox object that is used to show the contents.

Object oExplanationPanel is a cWebPanel
    Object oWebDocumentationBox is a cWebHtmlBox
        Set psHtmlId to "SolutionText"
        Set pbServerOnClick to True
        Set pbFillHeight to True
        Procedure OnClick String sId String sParam
            Handle hoView
            Case Begin
                Case (sId = "openview")
                Get WebObjectByName sParam to hoView
                Send Show of hoView
                Case Break
                Case (sId = "navigate")
                Send NavigateToPage of oWebApp sParam btNewTab
                Case Break
            Case End

Special in the oWebDocumentationBox object is the psHtmlId setting and the OnClick event implementation. The psHtmlId is set to make it possible for the web designers to style the content of the HTML text stored in the Documentation table. The OnClick event is fired if the user clicks a anchor element in the HTML text that contains a data-serveronclick attribute. Check out the documentation of this setting within the DataFlex Web Application Framework documentation.
Finally this solution page contains two buttons below the treeview that would bring the user to the websites for DataFlex Reports and DataFlex.