TeamConnect Custom Tool pageDetail Reference Guide
1. What is pageDetail?
pageDetail is the reserved root variable in TeamConnect Custom Tool XML pages that refers to the Java backing class instance for the tool. It is automatically bound by the TC framework when the custom tool page renders.
- It is NOT the core DLPageDetail used internally by the TC UI framework for entity views.
- It is the data model + controller for your custom tool page.
- The name pageDetail is fixed and cannot be renamed (e.g., you cannot use customTool.xxx or myPage.xxx).
How it works
Custom Tool XML Page (UI) ──── pageDetail ────> Java Backing Class (Logic)
${pageDetail.myList} reads from getMyList()
PD__MyField__STR writes to setMyField(String)
invokePageDetailAction calls method myMethod()
The JSP host page (toolCustom.jsp) renders the custom tool via the <teamconnect:customTool /> tag (class: com.mitratech.teamconnect.webui.taglib.CustomToolTag), which transforms your XML using the pageDetail object as the data context.
2. XML Page Structure
Every custom tool page is an XML file wrapped in a <tc:transform> root element.
Namespace: v1.0 (Custom Tools)
All OOTB Custom Tools use the v1.0 namespace. Within v1.0, there are two syntax styles:
Older style (uses condition= and CL-prefixed components):
<tc:transform version="1.0" xmlns:tc="http://www.w3.org/1999/XSL/Transform">
<tc:if condition="pageDetail.isEnabled">
<tc:CLLabel label="Hello" name="myLabel" />
<tc:CLTextField id="myField" name="PD__MyField__STR" size="50"/>
<tc:CLCheckBox name="PD__MyFlag__BOOL" id="myFlag" />
<tc:CLDropDownList name="PD__MySelect__OBJ" list="pageDetail.getMyList" />
</tc:if>
</tc:transform>
Newer style (uses test= with EL syntax — still v1.0 namespace):
<?xml version="1.0" encoding="UTF-8"?>
<tc:transform version="1.0" xmlns:tc="http://www.w3.org/1999/XSL/Transform">
<tc:if test="${pageDetail.isEnabled()}">
<tc:label key="my.label.key" name="myLabel" colon="true"/>
<tc:out value="${pageDetail.myValue}" />
<tc:select name="PD__MySelect__OBJ" list="${pageDetail.getMyList()}" />
</tc:if>
</tc:transform>
Both styles work within the v1.0 namespace. OOTB tools like AlternativeFeeArrangementSetting use the older condition= style, while AccountConversionTool and TCLTimeEntrySYS use the newer test= EL style — all with the same v1.0 namespace.
Namespace: v4.0 (Screen Designer Screens)
The v4.0 namespace is primarily used by Screen Designer screens (.scr.xml), not Custom Tools. These screens use tc:useClass to declare named Java class instances instead of pageDetail:
<?xml version="1.0" encoding="UTF-8"?>
<tc:transform xmlns:tc="http://www.mitratech.com/schemas/2008/custom" version="4.0">
<tc:useClass name="MyCustomBlock" id="cjb"/>
<tc:blockTemplate blockTitleKey="my.block.title" showEdit="false">
<tc:if test="${cjb.enabled}">
<tc:text name="UM_myField" value="${cjb.myValue}" forceNotEditable="true" />
<tc:out value="${cjb.status}" />
</tc:if>
</tc:blockTemplate>
</tc:transform>
It IS possible to use the v4.0 namespace for Custom Tools (where pageDetail still works), but this is not the typical OOTB pattern.
Syntax comparison
|
Feature |
Older style (v1.0) |
Newer style (v1.0 & v4.0) |
|---|---|---|
|
Conditionals |
<tc:if condition="pageDetail.isXxx"> |
<tc:if test="${pageDetail.isXxx()}"> |
|
Negation |
negate="1" or negate="true" (both work) |
negate="true" |
|
Output |
<tc:component componentType="WOString" value="pageDetail.xxx" /> |
<tc:out value="${pageDetail.xxx}" /> |
|
Labels |
<tc:CLLabel label="text" /> |
<tc:label key="i18n.key" /> |
|
Text fields |
<tc:CLTextField /> |
<tc:text /> |
|
Checkboxes |
<tc:CLCheckBox /> |
(no CL-free equivalent observed in Custom Tools) |
|
Dropdowns |
<tc:CLDropDownList list="pageDetail.xxx" /> |
<tc:select list="${pageDetail.xxx()}" /> |
|
Property access |
pageDetail.propertyName (no EL) |
${pageDetail.propertyName} (EL syntax) |
|
Root variable |
pageDetail (Custom Tools) |
pageDetail (Custom Tools) or cjb etc. (Screen Designer) |
3. Reading Data from pageDetail
Simple property access
Accesses the getter method on the Java backing class.
<!-- Newer style: calls getJobStatus() -->
<tc:out value="${pageDetail.jobStatus}" />
<!-- Older style: calls getExceedFeesChargeRuleName() -->
<tc:component componentType="WOString" value="pageDetail.exceedFeesChargeRuleName" />
Boolean conditions
<!-- Newer style: calls isRunning() -->
<tc:if test="${pageDetail.isRunning()}">
Running...
</tc:if>
<!-- Newer style negation: calls isRunning(), shows content when false -->
<tc:if test="${pageDetail.isRunning()}" negate="true">
Not running.
</tc:if>
<!-- Older style: calls getIsAFAEnabled() or isAFAEnabled() -->
<tc:if condition="pageDetail.isAFAEnabled">
AFA is enabled.
</tc:if>
<!-- Older style negation -->
<tc:if condition="pageDetail.isAFAEnabled" negate="1">
AFA is not enabled.
</tc:if>
Compound conditions (EL syntax only)
Use && for AND (XML-escaped &&). Requires test= attribute (not condition=):
<tc:if test="${pageDetail.hasCategoryRights && pageDetail.hasViewRights}">
...
</tc:if>
Iterating lists
<!-- Newer style (EL) -->
<tc:forEach items="${pageDetail.stringList}" var="pageDetail.thisString">
<tc:out value="${pageDetail.thisString}" />
</tc:forEach>
<!-- With nested object properties -->
<tc:forEach items="${pageDetail.columnInfoList}" var="pageDetail.columnInfo">
<tc:out value="${pageDetail.columnInfo.labelI18nKey}" />
<tc:out value="${pageDetail.columnInfo.fieldName}" />
</tc:forEach
How tc:forEach works:
- items — calls the getter (e.g., getStringList()) to get the collection
- var — on each iteration, calls the setter (e.g., setThisString(item)) on the pageDetail
- Inside the loop, ${pageDetail.thisString} calls getThisString() to read the current item
Displaying lists in dropdowns
<!-- Newer style -->
<tc:select name="PD__CustomObject__OBJ"
list="${pageDetail.getCustomObjects()}"
value="${pageDetail.selectedObjd}"
allowNullValue="false" />
<!-- Older style -->
<tc:CLDropDownList name="PD__AdjustReason__OBJ"
list="pageDetail.getAdjustmentReasonList"
displayStringPath="name"
allowNullValue="true"
isAlwaysEditable="true" />
4. Writing Data to pageDetail — The PD__ Naming Convention
Form field names use a special naming convention that tells TC how to map user input back to the pageDetail Java class:
PD__<PropertyName>__<Type>
Type suffixes
|
Suffix |
Java Type |
Description |
|---|---|---|
|
__STR |
String |
Text input |
|
__BOOL |
boolean |
Checkbox (true/false) |
|
__OBJ |
Object |
Dropdown/select (entity reference) |
|
__INT |
int |
Numeric input |
|
__DATE |
Date |
Date picker |
Examples
<!-- Text field: calls setMyField(String) on pageDetail -->
<tc:CLTextField id="myField" name="PD__MyField__STR" size="50"/>
<!-- Checkbox: calls setIsActive(boolean) on pageDetail -->
<tc:CLCheckBox name="PD__IsRuleActive_FeeChargesExceedFixedFee__BOOL" id="myCheck" />
<!-- Dropdown: calls setAdjustReason(Object) on pageDetail -->
<tc:CLDropDownList name="PD__AdjustReason_FeesExceedsCappedFee__OBJ"
list="pageDetail.getCappedFeeAdjReasonList"
displayStringPath="name"
allowNullValue="true" />
Alternative name patterns
Besides the PD__xxx__TYPE convention, two other patterns are used in OOTB tools:
blockValues['xxx'] — used for key-value settings (seen in TCLTimeEntrySYS):
<tc:select name="blockValues['ShowSelected']"
list="${pageDetail.showList}" />
pageDetail.xxx — used with tc:date to bind directly to a pageDetail property:
<tc:date id="timePeriodDate" name="pageDetail.timePeriodDate" />
PD__BlockValue_xxx__TYPE — a sub-pattern of the PD__ convention for settings stored as block values:
<tc:CLCheckBox name="PD__BlockValue_AFAFixedFeeMatterBasedEnabled__BOOL" /> <tc:CLDropDownList name="PD__BlockValue_AFACappedFeeEnabledAFT__OBJ" />
5. Calling Methods on pageDetail — Actions
Using invokePageDetailAction
Executes a method on the Java backing class from a button click:
<input class="mainSearchBtn" id="BUTTON_refresh" name="refresh"
onclick="invokePageDetailAction(this, 'BUTTON_refresh', 'refresh(*STR)', 'PD__CustomObject__OBJ');"
type="button" value="${pageDetail.getRefreshKey()}" />
Syntax:
invokePageDetailAction(eventSource, anchorId, 'methodName(*TYPE, *TYPE)', 'fieldName1', 'fieldName2');
- eventSource — usually this
- anchorId — element ID to focus after reload (e.g., 'BUTTON_refresh')
- methodName(...) — the method to call on pageDetail, with parameter type markers
- *STR — reads value from the named form field as String
- *OBJ — reads value as Object
- *BOOL — reads value as boolean
- Remaining args — form field names whose values are passed as method parameters
Using invokeToolAction
Simpler syntax (the JS framework labels this as a "4.x tool action", but it is available globally):
// No parameters
invokeToolAction('myAction')
// With parameters
invokeToolAction('myActionWithArgs', arg1, arg2)
Using top.submitCommand (older style)
Direct command submission used in older-style tools:
<!-- Simple submit -->
<input type="button" value="Save" onclick="top.submitCommand('_self','','PD', 'submit()')" />
<!-- Submit with specific action -->
<input type="button" value="Save AFA Settings"
onclick="top.submitCommand('_self','','PD', 'updateAFASettings()')" />
<!-- Checkbox onChange triggers submit -->
<tc:CLCheckBox name="PD__MyFlag__BOOL" id="myFlag"
onClick="top.submitCommand('_self',this.name,'PD', 'submit()')" />
6. Available TC XML Tags
Display tags
|
Tag |
Style |
Purpose |
Example |
|---|---|---|---|
|
tc:out |
Newer |
Output a value |
<tc:out value="${pageDetail.name}" /> |
|
tc:component |
Older |
Output a value |
<tc:component componentType="WOString" value="pageDetail.name" /> |
|
tc:message |
Both |
Display i18n text |
<tc:message key="common.status" /> |
|
tc:messageParam |
Both |
Parameter for message |
<tc:messageParam value="${pageDetail.count}" /> |
|
tc:label |
Newer |
Form label (i18n) |
<tc:label key="my.key" name="field" colon="true" /> |
|
tc:CLLabel |
Older |
Form label (literal) |
<tc:CLLabel label="My Label" name="field" /> |
Input tags
|
Tag |
Style |
Purpose |
|---|---|---|
|
tc:CLTextField |
Older |
Text input |
|
tc:text |
Newer |
Text input (seen in Screen Designer screens) |
|
tc:CLCheckBox |
Older |
Checkbox |
|
tc:CLDropDownList |
Older |
Dropdown |
|
tc:select |
Newer |
Dropdown |
|
tc:date |
Both |
Date picker |
Navigation tags
|
Tag |
Style |
Purpose |
|---|---|---|
|
tc:CLAnchor |
Older |
Hyperlink with JS action (e.g., <tc:CLAnchor href="myAction()">) |
Control flow tags
|
Tag |
Style |
Purpose |
|---|---|---|
|
tc:if |
Both |
Conditional rendering (supports both condition= and test=) |
|
tc:forEach |
Both |
Loop over a collection |
Screen Designer tags (v4.0 namespace)
|
Tag |
Purpose |
|---|---|
|
tc:useClass |
Declares a named Java class instance (e.g., <tc:useClass name="MyBlock" id="cjb"/>) |
|
tc:blockTemplate |
Wraps content in a titled block with optional edit mode |
Batch display tags
|
Tag |
Purpose |
|---|---|
|
tc:batchDisplay |
Renders a data grid with add/remove/update row actions |
|
tc:batchDisplayTextColumn |
Text column in batch display |
|
tc:batchDisplayNumberColumn |
Number column in batch display |
|
tc:batchDisplayDateColumn |
Date column in batch display |
|
tc:batchDisplayProjectColumn |
Project picker column in batch display |
|
tc:batchDisplayCategoryItemColumn |
Category picker column in batch display |
Batch display example
<tc:batchDisplay actionNames="${pageDetail.actionNames}"
batchDisplayObject="pageDetail.batchDisplayObject"
hideUpdateFunction="true" hideRemoveFunction="true" hideAddFunction="true">
<tc:batchDisplayTextColumn name="displayString"
labelI18nKey="my.column.header" required="false" width="50%" />
<tc:batchDisplayTextColumn name="currentPhaseType.name"
labelI18nKey="phase.itemName" required="false" width="10%" />
</tc:batchDisplay>
7. Custom Tool File Structure
Each custom tool in TeamConnect consists of:
Tools/
MyToolName/
Classes/ ← Java .class files (compiled backing class)
Resource/
MyToolName.xml ← The XML page definition (uses pageDetail)
The Classes folder contains the compiled Java class that IS the pageDetail object. The Resource folder contains the XML that defines the UI.
8. Java Backing Class Requirements
The Java backing class must:
- Extend the appropriate TC custom tool base class
- Provide getters for every ${pageDetail.xxx} referenced in the XML
- Provide setters for every PD__Xxx__TYPE form field and every tc:forEach var="pageDetail.xxx"
- Implement action methods called by invokePageDetailAction or invokeToolAction
Minimal example
public class MyToolPageDetail extends TCCustomToolPageDetail {
private String myField;
private boolean myFlag;
private List<String> myList;
private String currentItem;
// Getter for: ${pageDetail.myField}
public String getMyField() { return myField; }
// Setter for: PD__MyField__STR
public void setMyField(String value) { this.myField = value; }
// Getter for: ${pageDetail.myFlag}
public boolean isMyFlag() { return myFlag; }
// Setter for: PD__MyFlag__BOOL
public void setMyFlag(boolean value) { this.myFlag = value; }
// Getter for: ${pageDetail.myList} (used by tc:forEach items=)
public List<String> getMyList() { return myList; }
// Setter for: tc:forEach var="pageDetail.currentItem"
public void setCurrentItem(String item) { this.currentItem = item; }
// Getter for: ${pageDetail.currentItem} (used inside tc:forEach)
public String getCurrentItem() { return currentItem; }
// Action method for: invokePageDetailAction(this, '', 'refresh(*STR)', 'PD__MyField__STR')
public void refresh(String selectedValue) {
// business logic
}
// Action method for: invokeToolAction('doSomething')
public void doSomething() {
// business logic
}
}
9. Real-World Examples from OOTB Tools
AlternativeFeeArrangementSetting (older style)
A settings tool that toggles AFA rule types on/off with configuration options.
Pattern: Uses condition= syntax, CL-prefixed components, and top.submitCommand for actions.
<tc:if condition="pageDetail.isAFACappedFeeEnabled">
<tc:CLCheckBox name="PD__IsRuleActive_FeesExceedsCappedFee__BOOL" id="myCheck"
onClick="top.submitCommand('_self',this.name,'PD', 'submit()')" />
<tc:CLDropDownList name="PD__AdjustReason_FeesExceedsCappedFee__OBJ"
list="pageDetail.getCappedFeeAdjReasonList"
displayStringPath="name" allowNullValue="true" isAlwaysEditable="true" />
</tc:if>
AccountConversionTool (newer style)
A batch processing tool that runs async jobs with status tracking.
Pattern: Uses test= with EL syntax (still v1.0 namespace), tc:forEach for failure lists, tc:batchDisplay for data grids, invokePageDetailAction for button actions.
<tc:if test="${pageDetail.isRunning()}">
<tc:out value="${pageDetail.jobStatus}" />
<tc:out value="${pageDetail.mattersProcessed}" />
</tc:if>
<tc:if test="${pageDetail.hasFailures()}">
<tc:forEach items="${pageDetail.failureList}" var="pageDetail.loopFailure">
<tc:out value="${pageDetail.loopFailureDisplayString}" />
</tc:forEach>
</tc:if>
TCLTimeEntrySYS (newer style)
A time entry tool demonstrating the newer EL-based syntax with v1.0 namespace.
Pattern: Uses test= with EL syntax, tc:date for date pickers, tc:select for dropdowns, blockValues for form fields, dynamic columns via tc:forEach.
<tc:select id="showList" list="${pageDetail.showList}"
name="blockValues['ShowSelected']"
onChange="invokePageDetailAction(this, 'showList', 'populateTaskList()');" />
<tc:date id="timePeriodDate" name="pageDetail.timePeriodDate" />
10. Quick Reference Card
|
What you want to do |
XML Syntax |
|---|---|
|
Read a String |
<tc:out value="${pageDetail.myProp}" /> |
|
Read a boolean |
<tc:if test="${pageDetail.isEnabled()}"> |
|
Negate a condition |
<tc:if test="${pageDetail.isEnabled()}" negate="true"> |
|
Loop a list |
<tc:forEach items="${pageDetail.myList}" var="pageDetail.currentItem"> |
|
Text input |
name="PD__MyField__STR" |
|
Checkbox |
name="PD__MyFlag__BOOL" |
|
Dropdown |
name="PD__MySelect__OBJ" list="${pageDetail.getOptions()}" |
|
Call a method |
invokePageDetailAction(this, '', 'myMethod()') |
|
Call with params |
invokePageDetailAction(this, '', 'myMethod(*STR)', 'PD__Field__STR') |
|
i18n message |
<tc:message key="my.i18n.key" /> |
|
Show a data grid |
<tc:batchDisplay batchDisplayObject="pageDetail.batchDisplayObject"> |
11. Common Pitfalls
- Cannot rename pageDetail — it is a reserved name bound by the framework for Custom Tools
- condition= vs test= — both work within the v1.0 namespace; older tools use condition= (no EL), newer tools use test= (with EL ${} syntax). Do not assume test= requires v4.0
- PD__ is not the only name pattern — blockValues['xxx'] and pageDetail.xxx are also valid (see Section 4)
- tc:forEach var= must use pageDetail.xxx — the var sets a property on the pageDetail, not a standalone variable
- Boolean getters — older style: condition="pageDetail.isXxx" (property-style), newer style: test="${pageDetail.isXxx()}" (method-style with EL)
- Dropdown list= syntax — older: list="pageDetail.getMyList" (no EL), newer: list="${pageDetail.getMyList()}" (EL)
- Null pageDetail — if there are errors rendering the tool, pageDetail will be empty; the host JSP checks <c:if test="${not empty pageDetail}"> before rendering
- Custom Tools vs Screen Designer — pageDetail is for Custom Tools only. Screen Designer screens use tc:useClass with named variables like cjb (see Section 12)
12. Screen Designer Screens vs Custom Tools
TeamConnect uses the <tc:transform> XML format in two distinct contexts:
|
Custom Tools |
Screen Designer Screens |
|
|---|---|---|
|
Location |
System > Tools > MyTool/Resource/ |
Object Definitions > OBJ/Documents/Screens/ |
|
File extension |
.xml |
.scr.xml or .xml |
|
Namespace |
||
|
Root variable |
pageDetail (fixed) |
Named via tc:useClass (e.g., cjb) |
|
Java class binding |
Automatic — the tool's backing class IS pageDetail |
Explicit — <tc:useClass name="MyBlock" id="cjb"/> |
|
Form field names |
PD__xxx__TYPE |
applicationEntity.xxx, UM_xxx, or blockValues['xxx'] |
|
Block wrapping |
None (tool renders full page) |
<tc:blockTemplate> wraps content in a titled UI block |
|
Entity access |
Via pageDetail methods |
${enterpriseEntity.xxx} for the current record |
Screen Designer example (v4.0)
<?xml version="1.0" encoding="UTF-8"?>
<tc:transform xmlns:tc="http://www.mitratech.com/schemas/2008/custom" version="4.0">
<tc:useClass name="KeyDatesTimelineBlock" id="cjb"/>
<tc:blockTemplate blockTitleKey="custom.common.KeyDates.BlockTitle" showEdit="false">
<tc:if test="${!enterpriseEntity.newEntity}">
<tc:out value="${cjb.myData}" />
</tc:if>
</tc:blockTemplate>
</tc:transform>

