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.

images/CustomControlExample.jpg

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.

    images/CustomControlsDBFCalc.jpg
  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