Skip to main content

Data Sources

Data Sources

A <tablePane> element must indicate a data source for the table in one of the following ways:

The next several topics describe each option in detail.

Regardless of which option you use, all techniques support the maxRows attribute. It controls the size of the data returned. The following table provides maxRows details.

Attribute Description
maxRows

The maximum number of rows to fetch. For ordinary tables this is the maximum number of rows to display. For snapshot tables, maxRows is the maximum size of the snapshot and pageSize is the number of rows to display per page. The default value for maxRows is 100.

The <radioSet>, <select>, <dataListBox>, <dataCombo>, and <repeatingGroup> components also support the maxRows attribute.

Specifying an SQL Query

A <tablePane> can provide a complete SQL statement as the value of its sql attribute. For example:

<tablePane id="table"
           sql="SELECT ID,Name FROM MyApp.Employees
                WHERE Name %STARTSWITH ? ORDER BY Name"
           >
     <parameter value="Z"/>
</tablePane>

The following table provides sql details.

Attribute Description
sql

The value of this attribute is a complete SQL statement, which Zen executes at runtime to provide the contents of the table. The <radioSet>, <select>, <dataListBox>, <dataCombo>, and <repeatingGroup> components also support the sql attribute.

You may provide any input parameter values for the SQL query by placing <parameter> elements inside the <tablePane> container. For details, see the section “Query Parameters.”

The sql attribute is the XML projection of the %ZEN.Component.tablePaneOpens in a new tab property sql. Therefore, the sql attribute value must escape any XML special characters. For example, in place of the less-than symbol < you must substitute the XML entity &lt; as follows:

sql="select * from infonet_daten.abopos where lieferadresse=? and status<9"

The following table lists XML special characters that cause problems when they appear in sql strings, and the XML entities to substitute for them.

XML Entities for Use in sql Attribute Values
Character XML Entity Description
> &gt; Right angle bracket or “greater than” symbol.
< &lt; Left angle bracket or “less than” symbol.
& &amp; Ampersand.
' &apos; Single quotation mark or apostrophe. A string enclosed in single quotes needs the &apos; entity to represent the ' character.
" &quot; Double quotation mark. A string enclosed in double quotes needs the &quot; entity to represent the " character.

Unlike most other %ZEN.Component.tablePaneOpens in a new tab properties, you cannot set the sql property from the client at runtime. You can set it only from XData Contents. This is because sql is an encrypted attribute. The sql attribute value is encrypted (using the current session key) when it is sent to the client. If this value is returned to the server, it is automatically decrypted.

This prevents users from seeing the definition of an SQL statement if they view page source within their browser and prevents client logic from constructing arbitrary queries. For security reasons, query activities should always be restricted to the server.

Generating an SQL Query

The <tablePane> component supports attributes that allow you to automatically generate the query based on a simple description. This approach is similar to using a callback method, as described in a later topic, except that Zen generates the callback method for you, based on your description of the query. <dataListBox> and <dataCombo> also supports these attributes.

Attribute Description
groupByClause An SQL GROUP BY clause such as "Year,State". The groupByClause value can be a literal string, or it can contain a Zen #()# runtime expression.
orderByClause An SQL ORDER BY clause such as "Name,State". If not provided, then whenever the user clicks on a column header, the next query contains the appropriate ORDER BY clause based on the user’s choice. The orderByClause value can be a literal string, or it can contain a Zen #()# runtime expression.
tableName The name of the SQL table that provides the data for the table. This value is used in the FROM clause for the generated query. The tableName value can be a literal string, or it can contain a Zen #()# runtime expression.
whereClause

An SQL WHERE clause such as "Name='Elvis'".

When a whereClause is provided in the <tablePane> definition in XData Contents, this sets an initial value for the whereClause property of the tablePane object. If client-side or server-side code later changes the value of this whereClause property, the new value overrides the original value. This means you can initially set up a table to show only certain values, but another line of code can change the whereClause value, causing your users to see a different set of values when it refreshes.

For example, if any column filters are defined in this table, Zen dynamically creates a WHERE clause for the <tablePane> based on the current filter values selected by the user.

The whereClause value can be a literal string, or it can contain a Zen #()# runtime expression.

To have the <tablePane> generate an SQL query, you must do the following:

  1. Provide a value for the tableName attribute.

  2. Do not provide values for the sql, queryClass, queryName, or OnCreateResultSet. All of these attributes take precedence over the behavior described in this topic.

    After you satisfy the first two conditions, Zen assumes a "columns" value for dataSource.

  3. Define the names of one or more columns by providing <column> elements inside the <tablePane>. You must define at least one column or Zen generates a “Missing SELECT list” error.

  4. You can add query parameters by providing <parameter> elements inside the <tablePane>.

  5. You can add clauses for the generated query by providing the <tablePane> attributes groupByClause, orderByClause, or whereClause, or by allowing defaults to prevail as described in the table above.

The following is a simple example:

<tablePane id="table"
    tableName="MyApp.Employee">
    <column colName="ID" hidden="true"/>
    <column colName="Name"/>
</tablePane>

This <tablePane> example generates an SQL statement similar to the following:

SELECT ID,Name FROM MyApp.Employee

Zen executes this query to provide the contents of the table. In the example, the ID column is marked as hidden. This means that its value is fetched (it can be used for conditions or actions) but not displayed. For details about hidden and other <column> attributes, see the section “Table Columns.”

Note:

A generated SQL query can be useful for tables with column filters.

Referencing a Class Query

A <tablePane> can reference a pre-existing class query to obtain a %ResultSetOpens in a new tab object. The following components also support this approach: <radioSet>, <select>, <dataListBox>, <dataCombo>, and <repeatingGroup>.

Attribute Description
queryClass The name of the class containing the query. You must also provide a value for queryName.
queryName The name of the class query that provides the %ResultSetOpens in a new tab for this <tablePane>. You must also provide a value for queryClass.

You may provide any input parameter values for the query by placing <parameter> elements inside the <tablePane>. For example:

<tablePane id="table"
           queryClass="MyApp.Employee"
           queryName="ListEmployees">
    <parameter value="Sales"/>
    <parameter value="NEW YORK"/>
</tablePane>

The value of the parameter in the <tablePane> is the value used to create the %ResultSetOpens in a new tab object. It overrides any default value set in the class query in all cases.

Using a Callback Method

A <tablePane> can use a callback method to obtain a %ResultSetOpens in a new tab object. The following <tablePane> attributes support this approach. <dataListBox>, <dataCombo>, and <altJSONSQLProvider> also support these attributes.

Attribute Description
OnCreateResultSet

Name of a server-side callback method in the Zen page class. For more information, see OnCreateResultSet.

OnExecuteResultSet

Name of a server-side callback method in the Zen page class. For more information, see OnExecuteResultSet.

showQuery

showQuery works only if an OnCreateResultSet callback is used to generate the table, and only if this callback sets the queryText property of the QueryInfo object to contain the text of the query. Of the various components that use callback methods to generate SQL queries, only <tablePane> and <dataCombo> support the showQuery attribute.

If showQuery is true, the Zen page displays the SQL query used to provide the contents of the <tablePane> or <dataCombo> component. This is useful for troubleshooting purposes, during application development. The default showQuery value is false.

showQuery has the underlying data type %ZEN.Datatype.booleanOpens in a new tab. See “Zen Attribute Data Types.”

The showQuery value can be a literal string, or it can contain a Zen #()# runtime expression.

OnCreateResultSet

Name of a server-side callback method in the Zen page class. This method instantiates the %ResultSetOpens in a new tab object and set any %ZEN.Auxiliary.QueryInfoOpens in a new tabQueryInfo Properties” appropriately. Zen invokes this method whenever it draws the table, automatically passing it the following parameters:

The callback must return a %ResultSetOpens in a new tab object. The following is a valid method signature. Also see the detailed example following this table:

Method CreateRS(Output tSC As %Status,
     pInfo As %ZEN.Auxiliary.QueryInfo)
     As %ResultSet
{ }

To use the above method as the callback, the developer would set OnCreateResultSet="CreateRS" for the <tablePane>.

If defined, OnCreateResultSet takes precedence over any other techniques for providing data for a <tablePane>.

OnExecuteResultSet

Name of a server-side callback method in the Zen page class. This method executes the %ResultSetOpens in a new tab object returned by the OnCreateResultSet callback. Zen automatically invokes the OnExecuteResultSet callback after the OnCreateResultSet callback, passing it the following parameters:

Optionally, you can suppress invocation of the OnExecuteResultSet callback by setting the QueryInfo queryExecuted property to true at the end of the OnCreateResultSet callback.

The OnExecuteResultSet callback must return a%ZEN.Datatype.booleanOpens in a new tab indicating whether or not the result set was executed. The following is a valid signature for this callback:

Method ExecuteRS(myRS As %ResultSet,
     Output pSC As %Status,
     pInfo As %ZEN.Auxiliary.QueryInfo)
     As %Boolean
{ }

To use the above method as the callback, the developer would set OnExecuteResultSet="ExecuteRS" for the <tablePane>.

Callback Example

The following is a detailed example of using a callback method to create a %ResultSetOpens in a new tab for a tablePane. The callback method constructs a dynamic SQL statement in response to current values of tablePane properties sortOrder and sortColumn. The tablePane automatically passes these values to the callback method as the corresponding properties of the input %ZEN.Auxiliary.QueryInfoOpens in a new tab object.

Also note how the method places the SQL statement text in the queryText property of QueryInfo before exiting. If the <tablePane> showQuery value is true, this table displays itself, plus the query that generated it.

Method CreateRS(Output tSC As %Status,
                pInfo As %ZEN.Auxiliary.QueryInfo) As %ResultSet
{
    Set tRS = ""
    Set tSC = $$$OK

    Set tSELECT = "ID,Name,Title"
    Set tFROM = "MyApp.Employee"
    Set tORDERBY = pInfo.sortColumn
    Set tSORTORDER = pInfo.sortOrder
    Set tWHERE = ""

    // Build WHERE clause based on filters
    If ($GET(pInfo.filters("Name"))'="") {
        Set tWHERE = tWHERE _ $SELECT(tWHERE="":"",1:" AND ") _
                "Name %STARTSWITH '" _ pInfo.filters("Name") _ "'"
    }
    If ($GET(pInfo.filters("Title"))'="") {
        Set tWHERE = tWHERE _ $SELECT(tWHERE="":"",1:" AND ") _
                "Title %STARTSWITH '" _ pInfo.filters("Title") _ "'"
    }

    Set sql = "SELECT " _ tSELECT _ " FROM " _ tFROM
    Set:tWHERE'="" sql = sql _ " WHERE " _tWHERE
    Set:tORDERBY'="" sql =
       sql _ " ORDER BY " _tORDERBY _ $SELECT(tSORTORDER="desc":" desc",1:"")

    Set tRS = ##class(%ResultSet).%New()
    Set tSC = tRS.Prepare(sql)
    Set pInfo.queryText = sql

    Quit tRS
}

QueryInfo Properties

The following table describes the properties on the %ZEN.Auxiliary.QueryInfoOpens in a new tab object that appears in the signature for both callback methods.

Like tablePane, the dataCombo, dataListBox, and repeatingGroup components can also use callbacks to generate a component from a %ResultSetOpens in a new tab. Some of the properties in the QueryInfo object apply only to tablePane queries. dataCombo, dataListBox, and repeatingGroup ignore any table-only properties, including those for columns, filters, and sorting.

Only tablePane and dataCombo support the queryText property.

QueryInfo Properties
Property Description
columnExpression The colExpression values from each <column> in the <tablePane>. columnExpression organizes these values as a multidimensional array subscripted by <column> colName.
columns The colName values from each <column> in the <tablePane>. columns organizes these values as a multidimensional array subscripted by column number (1–based).
filterOps The filterOp values from each <column> in the <tablePane>. filterOps organizes these values as a multidimensional array subscripted by <column> colName.
filters The filterValue values from each <column> in the <tablePane>. filters organizes these values as a multidimensional array subscripted by <column> colName.
filterTypes The filterType values from each <column> in the <tablePane>. filterTypes organizes these values as a multidimensional array subscripted by <column> colName.
groupByClause The groupByClause value for the <tablePane>, if supplied.
orderByClause The orderByClause value for the <tablePane>, if supplied.
parms Multidimensional array, subscripted by parameter number (1–based). This array contains any input values provided by <parameter> elements within the <tablePane>.
queryExecuted Set this property to true in the method identified by OnCreateResultSet, to indicate that the newly created %ResultSetOpens in a new tab has already been executed and you do not want the method identified by OnExecuteResultSet to be called. The default is false.
queryText The method identified by OnCreateResultSet can set this value to the actual query text, to be displayed if the showQuery value is true.
rowCount

If this value is set by the callback, upon return the rowCount property contains the number of rows returned by the query. After the query is executed, rowCount could be different from rows.

Note that rowCount is a string, and not numeric, as its value might be "" or "100+". Any number of rows greater than 100 is represented as "100+". When testing rowCount from JavaScript, if you want to convert to a numeric value use parseInt for base 10:

rowCount = parseInt(rowCount,10);

rows The number of rows requested. For tables, this is the maxRows value.
sortColumn The colName of the current sort column selected by the user.
sortOrder The table’s current sort order (usually determined by user clicks) such as "asc" or "desc".
tableName The <tablePane> tableName value.
whereClause The whereClause value for the <tablePane>, if supplied.

Changing the Data Source Programmatically

You can change the data source for a <tablePane> at runtime in a variety of ways. The principle at work here is that the data source is on the server, so if you want to change the data source for a table based on user actions on the client side, you must work your way back to the server, as this topic shows.

In the following example, queryClass and queryName were used to define the data source, so we need to change them to new values on the server side. This example uses a JavaScript method in step 2 and a ZenMethod in step 3. Using an intervening JavaScript method as in step 2 is convenient if there are other actions you need to perform on the client side while changing the data source. Alternatively, the onclick from step 1 could invoke the ZenMethod directly, bypassing step 2:

  1. There is a component on the Zen page whose response to onclick (or to some other user action) is to invoke a client side JavaScript method. For example:

    <button caption="Display Form" onclick="zenPage.setUpContextForm()" />
    
    
  2. The client side JavaScript method invokes a server side ZenMethod that manipulates data source properties of the <tablePane>. For example:

     ClientMethod setUpContextForm() [ Language = javascript ]
    {
      this.SetQueryClassAndName("LTD.DomainModel.ContextList","GetAll")
      ctrl = this.getComponentById('ctrlList')
      ctrl.setModelClass('LTD.DomainModel.ContextList',this.getCurrentListId())
      zenSetProp('ContextId', 'hidden', 0)
      zenSetProp('ContextType', 'hidden',0)
    }
  3. The server side ZenMethod gets the <tablePane> component and set its data source properties. For example:

    Method SetQueryClassAndName(queryClass As %String, 
                                queryName as %String) 
                                As %Status [ ZenMethod ]
    {
      Set obj=%page.%GetComponentById("listTable")
      Set obj.queryClass = queryClass
      Set obj.queryName = queryName
      Quit $$$OK
    }
    
FeedbackOpens in a new tab