Template Modifier Files

Template Modifier Files (TMFs) allow Logi Info developers to modify the "super-elements", such as the Analysis Grid, which behave like mini-applications, have a UI, and let users control visualizations at runtime. In addition, Logi Info developers can use TMFs to create Themes. These interesting files are discussed in this topic.

  Looking for information about Excel, Word, or PDF templates? Template Modifier Files are not related to them; seeForm-based Reporting for information about those date-related templates.

For more information about Themes, see Themes.


About Template Modifier Files

Super-elements are a complex combination of standard elements, JavaScript, and style classes. The following super-elements can be customized using a TMF:

  • Analysis Chart
  • Analysis Filter
  • Analysis Grid
  • Chart Grid
  • Dashboard
  • Dimension Grid
  • OLAP Grid
  • Schedule
  • Report Author

Super-elements are rendered at runtime using a special definition file and standard Logi Info elements. A TMF is a separate definition file that's processed after a super-element's definition file, providing an opportunity to alter the super-element at runtime, without editing the fundamental super-element blueprint. UI customizations can be placed in a TMF to alter the appearance and behavior of the super-element.

Examples of common customizations using TMFs include language- and culture-specific text changes for internationalization, and the hiding of some of controls, such as Export buttons.

A TMF is an XML file that contains special tags for customizing the super-element. It can be stored in any folder accessible to the web application and it's specified in a super-element's Template Modifier File attribute. If a fully-qualified file path is not provided in the attribute value, then the application expects it to be in your application's _SupportFiles folder.

Tokens can be used in the Template Modifier File attribute to provide the TMF filename. This allows you to specify different TMFs (or no TMF) for different situations and/or different users.

Template modifier files are also a primary component of Logi Themes technology. The power of the TMF is quite obvious in this scenario, as it effectively "scripts" the output of the designated report to adopt the desired appearance.

When debugging links are turned on and TMFs are used, special entries will appear in the Debugger Trace report (see Debug Reports):
 

As shown above, these entries will be in the AnalysisGrid section. Click them to view the TMF log and the source code of the modified definition.
 

<Column> Element vs. <Column> Tag

Although the proper terminology for an XML object is "element", the term "tag" will be used in the following discussion in order to avoid confusion between super-elements, underlying elements, and XML elements.

Back to top

 

Setting Hidden Underlying Element Attributes

As mentioned earlier, some aspects of the appearance and behavior of a super-element can be configured using its exposed attributes (those that appear in Studio in the Attributes Panel). Further customization can occur by using a TMF to change its hidden attributes: the attributes of the underlying elements that make up the super-element.

The key to configuring hidden attributes is knowing the ID of the underlying elements.

The IDs of these underlying elements can be found by examining the special definition file that defines each super-element. These files are located in your application's rdTemplate folder. Here are a few of them:
 

Super-ElementTemplate File
Analysis ChartrdTemplate\rdAnalysisChart\rdAcTemplate.lgx
Analysis Filter rdTemplate\rdAnalysisFilter\rdAfTemplate.lgx
Analysis GridrdTemplate\rdAnalysisGrid\rdAg10Template.lgx
DashboardrdTemplate\rdDashboard\rdDashboard2Template.lgx
Dimension GridrdTemplate\rdOlapGrid\rdDgTemplate.lgx
OLAP GridrdTemplate\rdOlapGrid\rdOgTemplate.lgx
SchedulerdTemplate\rdSchedule\rdScheduleTemplate.lgx
Report AuthorrdTemplate\ReportAuthorTemplate.lgx

Never edit these files directly; only examine them to determine element IDs!

Here's a simple example of how TMFs are used. Suppose we want to change the Layout "descriptive text" that appears in an Analysis Grid.
 


When the Filter tab is clicked and the Filter configuration panel appears in an Analysis Grid, as shown above, the highlighted descriptive text is displayed.

To change this text to French, we first examine the Analysis Grid's definition file, rdAg10Template.lgx, with Notepad or a suitable text editor:
 

<Label ID="lblFilterDescription" Class="rdAgContentHeading" Caption="Filter rows by cell values." />

If we search the file for "filter rows", we'll find the code shown above. It contains a Label element, with an ID attribute of "lblFilterDescription", that sets the text we want to change. Note the ID of this element for use in our TMF.
 

<TemplateModifier>
    <SetAttribute ID="lblFilterDescription" Caption="
Filtrer par les valeurs des cellules." />
</TemplateModifier>

To cause the change, we create a TMF, as shown above, which we'll give the arbitrary filename AGFrenchTMF.xml.

This is a standard XML file, which starts and ends with the <TemplateModifier> tag. It uses a special TMF tag <SetAttribute> to make the change and the element to be changed is identified using its ID from the Analysis Grid's template definition file ("lblLayoutDescription"). The attribute to be changed is identified as the Caption and is given its new French text value.  

Next we save the TMF file to the application's _SupportFiles folder and, finally, enter its filename as the Analysis Grid's Template Modifier File attribute value, as shown above.
 

And the resulting change, shown above, can be seen when the report is run again.
  Now that you've seen the basic concept in action, here's a more complicated TMF example:
 

<ExampleTMF>
     <!-- These SetAttributes will change the Formula Column Panel Text  -->
    <SetAttribute ID="lblFormulaColumnDescription" Caption="Formule de la colonne" />
    <SetAttribute ID="lblCalcHelp" Caption="Formule Aide" />
    <SetAttribute ID="lblCalcName" Caption="Nom" />
    <SetAttribute ID="lblCalcInsertDataColumn" Caption="Inserer une colonne" />
    <SetAttribute ID="lblCalcInsertDataColumnNow" Caption="Inserer" />
    <SetAttribute ID="lblCalcFormula" Caption="Formule" />
    <SetAttribute ID="lblCalcDataType" Caption="Type de donnees" />
    <SetAttribute ID="lblCalcDisplayFormat" Caption="Format d'affichage" />
    <SetAttribute ID="lblCalcOk" Caption="Ajouter" />
 </ExampleTMF>


Note that actual <TemplateModifier> tags are not required; any tags that properly open and close the XML are acceptable. Also note that comments can be embedded into the XML using the HTML <!-- ... --> comment syntax.
 

The resulting changes are shown above. This example changed the section description, field captions, and button captions to French.

If a Security Right ID attribute is being set, the element is re-evaluated after the operation for security purposes.

Back to top

 

Using XPath Notation

The TMF examples shown so far have used element IDs to identify elements whose attributes are to be changed. However, XPath notation can be used instead, if preferred.
 

<TemplateModifier>
  <SetAttribute
XPath="//Label[@ID='lblFilterDescription']" Caption="
Filtrer par les valeurs des cellules." />
 </TemplateModifier>

The example shown above uses an earlier TMF example with XPath notation, instead of an element ID. XPath can be very useful when you want to identify multiple elements with similar names or types.

See this external site for more information about XPath syntax.

Back to top

 

Modifying Selected Chart Captions

 When you create charts using the Analysis Chart or Analysis Grid super-elements, the chart caption is created automatically and appears in a format similar to:

    Sum of OrderID by OrderDate

You may wish to translate this caption and/or reorder its parts, and this can be done using a TMF. Here's an example of the relevant code in the Analysis Chart template file (rdTemplate/rdAnalysisChart/rdAcTemplate.lgx):
 

<ChartCanvas ChartCaption="{AggrName} of {DataColumnName} by {LabelColumnName}" CaptionDated="{AggrName} of {DataColumnName} by {LabelColumnName}" ChartHeight="300" ChartWidth="500" BorderColor="#7A7A7A" BorderRadius="4" ID="ChartPie" rdUnderSuperElement="True">

Note the construction of the default ChartCaption and CaptionDated attribute values, highlighted above. The items within the curly braces are internal chart variables and, using a TMF, you can substitute a different value that includes them, as follows:
 

<SetAttribute XPath="//ChartCanvas" ChartCaption="{AggrName} de {DataColumnName} par {LabelColumnName}" />

The example TMF code shown above translates the English connecting words "of" and "by" to their French equivalents. You can change the value in any way you desire, using the { } chart variables or removing them altogether.
 

<SetAttribute XPath="//ChartCanvas" ChartCaption="{DataColumnName} by {LabelColumnName}: {AggrName}" />

You can also rearrange the value parts, as shown above. The resulting caption would appear as "OrderID by OrderDate: Sum". 

Back to top

 

Manipulating Existing Underlying Elements

Some of the super-elements include static data sets, such as Format options, that are presented in the user interface as drop-down selection lists. TMFs can also be used to alter this data.
 

For example, in the Analysis Grid's Formula tab, the user can select from a list of six pre-defined display format options, shown above. Let's see how we can use a TMF to change the format options.
 

<Column ID="col2Row5Calc">
   <InputSelectList OptionValueColumn="Format" ID="rdAgCalcFormats" IncludeBlank="True" OptionCaptionColumn="FormatName" DefaultValue="@Request.rdAgCalcFormats~">
      <DataLayer Type="Static" ID="dlCalcFormats">
         <StaticDataRow Format="###,###,##0.00" FormatName="###,###,##0.00" />
         <StaticDataRow Format="$###,###,##0.00" FormatName="$###,###,##0.00" />
         <StaticDataRow Format="yyyy/MM/dd" FormatName="yyyy/MM/dd" />
         <StaticDataRow Format="yyyy/MM/dd hh:mm:ss" FormatName="yyyy/MM/dd hh:mm:ss" />
         <StaticDataRow Format="MM/dd/yyyy" FormatName="MM/dd/yyyy" />
         <StaticDataRow Format="MM/dd/yyyy hh:mm:ss" FormatName="MM/dd/yyyy hh:mm:ss" />
      </DataLayer>
   </InputSelectList>
</Column>

If we look at Analysis Grid's template definition file again, we find the above code that shows a DataLayer.Static element and child Static Data Row elements are used by default to create the six standard format options. In order to change that list, we need to do two things:

  1. Provide an XML data file that contains the data for our custom option list, and
  2. Override the existing datalayer, replacing it with a DataLayer.XML element that will read our custom option list file.

Here's the XML data file with our nine custom format options:
 

<MyCustomFormats>
   <Option Format="###,###,##0.00" FormatName="###,###,##0.00"/>
   <Option Format="$###,###,##0.00" FormatName="$###,###,##0.00"/>
   <Option Format="Short Date" FormatName="Short Date"/>
   <Option Format="MMM dd yyyy" FormatName="MMM dd yyyy"/>
   <Option Format="MMMM dd yyyy" FormatName="MMMM dd yyyy"/>
   <Option Format="yyyy/MM/dd" FormatName="yyyy/MM/dd"/>
   <Option Format="yyyy/MM/dd hh:mm:ss" FormatName="yyyy/MM/dd hh:mm:ss"/>
   <Option Format="MM/dd/yyyy" FormatName="MM/dd/yyyy"/>
   <Option Format="MM/dd/yyyy hh:mm:ss" FormatName="MM/dd/yyyy hh:mm:ss"/>
 </MyCustomFormats>

Note that the column names ("Format" and "FormatName") in the XML data file mustmatch those used in the original Static Data Row elements in the Analysis Grid template definition file. Our custom format options file is stored in the application's _SupportFiles folder as MyCustomFormats.xml
 

<TemplateModifier>
    <SetAttribute XPath="//Column[@ID='col2Row5Calc']/InputSelectList/DataLayer" Type="XMLFile"
        XMLFile="MyCustomFormats.xml" />
 </TemplateModifier>

Finally, we need to create the TMF shown above. It uses XPath notation to change the type of the existing template DataLayer.Static element to a DataLayer.XML element and specifies MyCustomFormats.xml, our custom options file, as the datasource. "Type" and "XML File/URL" are standard attributes of the DataLayer.XML element. When this file has been created and saved to _SupportFiles, all we need to do is set the Analysis Grid's Template Modifier File attribute to our TMF filename and preview it.  

The resulting Display Format option list is shown above and it now contains our nine custom format options. This example demonstrates that TMFs are not limited to mere text changes, but can also be used to manipulate existing elements in more interesting ways.  

Working with Underlying Datalayers

In many cases, the text that appears in super-element interfaces is drawn from internal static datalayers. Suppose you needed to change specific text that comes from one of these datalayers, for example, into a different language. To do this you would:

  1. Provide an XML data file, in _SupportFiles, that includes the translated text.
  2. Use a TMF to change the relevant internal datalayer element type from "Static" to "XML File" and to point it at your XML data file.
  3. In the TMF, change the internal Label element that displays the text to use @Data tokens.

There is one complication here: tokens inside the TMF itself are evaluated prior to being used in the modification. This is because you might have @Local, @Request, or other tokens that need to be evaluated in this file prior to being used. However, that won't achieve the "later" evaluation that we need to put the token values in the user interface. To get around this, you need to "escape" the @Data token used in your TMF for Step #3 above like this:


       @@Data.dummy~Data.columnName~


This is a "token-within-a-token" construction, where @Data.dummy~ is an arbitrary, dummy token and Data.columnName is the @Data token and column name from the XML data file. When the report runs and the TMF is evaluated, the dummy token will be evaluated first, to an empty string, leaving the real @Data token to be recognized and evaluated later. The odd construction above has the result of masking the fact that @Data.columnName~ is a token during the first evaluation.

Back to top

 

Inserting and Removing Underlying Elements

You can also use TMFs to insert, remove, and remark the internal elements that make up a super-element. This is accomplished using these XML tags:

  • <PrependChildElement>
  • <AppendChildElement >
  • <InsertBeforeElement >
  • <InsertAfterElement >
  • <Remark >
  • <RemoveElement >

The first four tags use a child tag, <NewElement>, to delimit the new element to be affected. The <Prepend- and <Append- tags make the new element the first or last child element in a group. See the section below about using the <NewElement> tag.

TMFs can insert Definition Modifier Files.

If elements affected by these operations have their Security Right ID attributes set, those attribute values will be evaluated before the modification is executed. This allows security rights to control which modifications are applied.

Here's a practical example of some of these elements in action:
 

An Analysis Grid can display three Export buttons, as shown above, and its Hide Exports attribute can be used to hide all three of them from users. However, if you use the attribute to hide the buttons, it's an "All-or-None" situation: developers can't choose to show a subset of the export buttons. A solution for those who wish to show a subset is to use a TMF. In the following example, we'll remove the CSV export button and add a Print button that mimics the PDF export functionality. One important thing to know when looking at the Analysis Grid's definition file to get the appropriate element IDs is that the export "buttons" are really Label elements made to look like buttons using CSS. Assuming the elements have been found and identified, the TMF can be written as follows:
 

<TemplateModifier>
    <RemoveElement ID="lblExportCsv" />
    <InsertAfterElement ID="lblExportPdf">
        <NewElement>
            <Label Caption="Print" ID="lblPrintBtn" Class="rdAgCommand" />
        </NewElement>
    </InsertAfterElement>
    <AppendChildElement ID="lblPrintBtn">
        <NewElement>
            <Action Type="PDF" ID="actExportPrint" />
        </NewElement>
    </AppendChildElement>
    <AppendChildElement ID="actExportPrint">
        <NewElement>
            <Target Type="PDF" Report="CurrentReport" ID="tgtExportPrint"/>
        </NewElement>
    </AppendChildElement>
    <InsertAfterElement ID="tgtExportPrint">
        <NewElement>
            <LinkParams rdAgNoDefCache="True" rdExportTableID="dtAnalysisGrid"/>
        </NewElement>
    </InsertAfterElement>
</TemplateModifier>


The first thing this TMF does is remove the CSV button ("lblExportCsv") using the <RemoveElement> tag.

Then three elements are appended, using the <InsertAfterElement> and <AppendChildElement> tags, creating the new Print button, its child Action element, and that element's child Target element. Where they are appended is specified in the tag's ID attribute. Note the use of the <NewElement> tag to delimit each element being added.

Finally, <InsertAfterElement> is used to add a LinkParams element at the same element hierarchy level as the Target element.
 

The resulting interface change is shown above. Note that it's possible to write the first part of the TMF in a more compact way, taking advantage of tag nesting:
 

<TemplateModifier>
    <RemoveElement ID="lblExportCsv" />

    
<InsertAfterElement ID="lblExportPdf">
        <NewElement>
            <Label Caption="Print" ID="lblPrintBtn" Class="rdAgCommand">
               <Action Type="PDF" ID="actExportPrint" >
                  <Target Type="PDF" Report="CurrentReport" ID="tgtExportPrint"/>
               </Action>
            </Label>
        </NewElement>
    </InsertAfterElement>
 </TemplateModifier>

As shown above, only one <InsertAfterElement> tag is necessary, as long as the opening and closing tags for the nested elements are arranged correctly.
 

<TemplateModifier>
    
<Remark>
        <RemoveElement ID="lblExportCsv" />
    
</Remark>

    <InsertAfterElement ID="lblExportPdf">
        <NewElement>
            <Label Caption="Print" ID="lblPrintBtn" Class="rdAgCommand">
               <Action Type="PDF" ID="actExportPrint" >
                  <Target Type="PDF" Report="CurrentReport" ID="tgtExportPrint"/>
               </Action>
            </Label>
        </NewElement>
    </InsertAfterElement>

    <InsertAfterElement ID="tgtExportPrint">
        <NewElement>
            <LinkParams rdAgNoDefCache="True" rdExportTableID="dtAnalysisGrid"/>
        </NewElement>
    </InsertAfterElement>
</TemplateModifier>

And, in the last variation, shown above, rather than removing tags, the <Remark> tag allows you to temporarily "comment out" portions of the TMFs, as shown above.
 

Using the <NewElement> Tag

Tags that insert or add a new element use the <NewElement> child tag set to enclose the element to be inserted:

<InsertAfterElement>
   <NewElement>
      <Division></Division>
   </NewElement>
</InsertAfterElement>

You may only insert one element per <NewElement> tag set, as shown above.
 

<InsertAfterElement>
   <NewElement>
      <Division></Division>
      <Division></Division>   <--- will be ignored
   </NewElement>
</InsertAfterElement>

You may not insert multiple elements per <NewElement> tag, as shown above.
  Instead use multiple <InsertAfterElement> (or similar) tags,

<InsertAfterElement>
   <NewElement>
      <Division>
         <Division></Division>
         <Division></Division>
      </Division>
   </NewElement>
</InsertAfterElement>

or wrap the multiple elements in a single top-level container element, as shown above.

Back to top

 

List of Special XML Tags

Here's a complete list of the special XML tags available for use in TMFs:
 

XML TagDescription
AppendChildElement Appends new child element as the last element beneath the element identified in its XML "ID" or "XPath" attribute. See section above about use of NewElement tag.
CutElement Used as a child of the Insert tags, this tag deletes the element identified by its XML "ID" or "XPath" attribute and makes it available for insertion. Used primarily to "move" elements within the definition.
CycleAttributeValuesUsed primarily with Themes, allows assignment of values to elements such as charts that have multiple layers. Elements to be modified are identified in its XML "CycleOnChildElement" attribute; uses child tag CycleValue.
CycleValueUsed to provide values for CycleAttributeValues tag.
InsertAfterElement Inserts new element after the element identified in its XML "ID" or "XPath" attribute. See section above about use of NewElement tag.
InsertBeforeElement Inserts new element before the element identified in its XML "ID" or "XPath" attribute. See section above about use of NewElement tag.
PrependChildElement Adds new child element as the first element beneath the element identified in its XML "ID" or "XPath" attribute. See section above about use of NewElement tag.
Remark"Comments" the XML tag it encloses, so the tag has no effect.
RemoveAttribute
Removes the attribute identified using its element XML "ID" or "XPath" and "AttributeName" attributes.
RemoveElement Removes the element identified in its XML "ID"  or "XPath" attribute.
SetAttribute Sets the attribute value identified for the element identified in its XML "ID" or "XPath" attribute, overwriting any value already there.
SetAttributeWhenEmpty Sets the attribute value identified for the element identified in its XML "ID" or "XPath" attribute, but only if that attribute does not have a value already.
SetAttributeWithInsert Inserts an additional attribute value before any existing value identified for the element identified in its XML "ID" or "XPath" attribute. This order is important, as it allows existing values related to CSS to "win" any conflicts by being last in the order.
UpdateOrAppendChildElement If the child element does not exist, appends it as the last element beneath the element identified in its XML "ID" or "XPath" attribute. If the child element exists, updates its attributes. See section above about use of NewElement tag.

Back to top