How to Use Custom Controls in a Grid Component

Description

This topic discusses an advanced use of a Custom Control in a Grid component.

Discussion

The image below shows a grid based on the Invoice_header table from Alphasports. The last column on the Grid shows the line-items (from the Invoice_items table) for the current invoice.

This data in this column is a custom control.

Here is how this was achieved:

  1. Create a dummy calculated field. Does not matter what the calculated field is called.

    The image below shows how you can do this for .dbf tables.

  2. In the case of SQL tables, you would create a custom SQL Select statement. For example:

    SELECT invoice_number, customer_id, date, sales_rep, delivery_by, '' as LinkedItems from Invoice_header
  3. Add the calculated field to the Grid and set its control type to the 'Custom'

  4. In the 'Custom Control Definition' add this Xbasic:

    function Linkeditems_render as c (data as p, args as p, PageVars as p)
    with PageVars
    
    on error goto Linkeditems_XbasicError
    linkeditems_render = linkedRecords(Data.Invoice_number,"GlassBlue")
    end
    
    Linkeditems_XbasicError:
    Linkeditems_render = "Error in custom control Xbasic: " + error_text_get()
    end with 
    end function
  5. In the 'Xbasic function declarations' section, define the linkedRecords() function.

    Here is a version of this function for the case where you are working with DBF files. An example for SQL tables follows below.

    function linkedRecords as c (invNo as c, style as c )
    
    dim tbl as p
    tbl =  table.open("PathAlias.ADB_Path\invoice_items")
    dim itbl as p
    itbl =  tbl.query_create("","invoice_number = " + s_quote(invNo)) 
    
    if  itbl.records_get() = 0 then 
    linkedRecords = "No records found"
    exit  function 
    end if 
    
    
    dim htmlTemplate as c 
    htmlTemplate =  <<%html%
    <tr>
    <td  class="{grid.style}DataTD">{a5_html_label(js_escape(tbl.data("product_id")))}</td>
    <td  class="{grid.style}DataTD"  style="text-align:right;">{a5_html_label(js_escape(tbl.data("price")))}</td>
    <td  class="{grid.style}DataTD"  style="text-align:right;">{a5_html_label(js_escape(tbl.data("quantity")))}</td>
    <td  class="{grid.style}DataTD"  style="text-align:right;">{a5_html_label(js_escape(tbl.data("extension")))}</td>
    </tr>
    %html%
    
    htmlTemplate  = stritran(htmlTemplate,"{grid.style}",style)
    
    dim html as c = ""
    while  .not. tbl.fetch_eof()
    *concat(html, evaluate_string(htmlTemplate) +  crlf())
    tbl.fetch_next()
    end while 
    
    
    dim titles as c 
    titles  = <<%html%
    
    <tr>
    <th  class="{grid.style}SorterLink">Product Id</th>
    <th  class="{grid.style}SorterLink">Price</th>
    <th  class="{grid.style}SorterLink">Quantity</th>
    <th  class="{grid.style}SorterLink">Extension</th>
    <th></th>
    </tr>
    %html%
    
    html  = "<table>" + crlf() + titles + crlf() + html + crlf() +  "</table>"
    
    html = <<%html%
    <fieldset  style="-moz-border-radius-topleft: 8px; -moz-border-radius-topright: 8px;  -moz-border-radius-bottomright: 8px; -moz-border-radius-bottomleft: 8px;  display: inline;" class="" >
    <legend style="color: Blue;"  class="">Invoice Items</legend> 
    %html% + html +  "</fieldset>"
    
    
    tbl.close()
    
    linkedRecords = html
    
    end function

Here is an example for SQL tables:

function linkedRecords as c (invNo as n, style as c )
dim cn as sql::connection

if cn.open("::name::alphasports") = .f. then 
    linkedRecords = "Error opening connection"
exit function 
end if 

dim sql as c 
sql = "select * from invoice_items where Invoice_number = :whatInvNo"

dim args as sql::arguments
args.add("whatInvNo",convert_type(invno,"N"))

if cn.Execute(sql,args) = .f. then 
    linkedRecords = "Error executing query"
    exit function 
end if 

if cn.ResultSet.nextrow() = .f. then 
    linkedRecords = "No records found."
    exit function 
end if 

dim htmlTemplate as c 
htmlTemplate = <<%html%
<tr>
<td class="{grid.style}DataTD">{a5_html_label(js_escape(cn.ResultSet.data("product_id")))}</td>
<td class="{grid.style}DataTD"  style="text-align:right;">{a5_html_label(js_escape(cn.ResultSet.data("price")))}</td>
<td class="{grid.style}DataTD"  style="text-align:right;">{a5_html_label(js_escape(cn.ResultSet.data("quantity")))}</td>
<td class="{grid.style}DataTD"  style="text-align:right;">{a5_html_label(js_escape(cn.ResultSet.data("extension")))}</td>
</tr>
%html%

htmlTemplate = stritran(htmlTemplate,"{grid.style}",style)

dim html as c = ""
dim flagRecordsFound as l = .t.
while flagRecordsFound
    *concat(html,  evaluate_string(htmlTemplate) + crlf())
    flagRecordsFound = cn.ResultSet.nextrow()
end while 

dim titles as c 
titles = <<%html%
<tr>
<th class="{grid.style}SorterLink">Product Id</th>
<th class="{grid.style}SorterLink">Price</th>
<th class="{grid.style}SorterLink">Quantity</th>
<th class="{grid.style}SorterLink">Extension</th>
<th></th>
</tr>
%html%

html = "<table>" + crlf() + titles + crlf() + html + crlf() + "</table>"
html = <<%html%
<fieldset style="-moz-border-radius-topleft: 8px; -moz-border-radius-topright: 8px; -moz-border-radius-bottomright: 8px; -moz-border-radius-bottomleft: 8px; display: inline;" class="" >
<legend style="color: Blue;"  class="">Invoice Items</legend> 
%html% + html + "</fieldset>"

cn.FreeResult()
cn.close()

linkedRecords = html

end function