![JAR search and dependency download from the Maven repository](/logo.png)
com.sencha.gxt.core.client.XTemplates Maven / Gradle / Ivy
/** * Sencha GXT 3.0.1 - Sencha for GWT * Copyright(c) 2007-2012, Sencha, Inc. * [email protected] * * http://www.sencha.com/products/gxt/license/ */ package com.sencha.gxt.core.client; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.i18n.client.NumberFormat; import com.google.gwt.safehtml.shared.SafeHtml; import com.sencha.gxt.core.client.XTemplates.FormatterFactories; import com.sencha.gxt.core.client.XTemplates.FormatterFactory; import com.sencha.gxt.core.client.XTemplates.FormatterFactoryMethod; import com.sencha.gxt.core.client.XTemplates.TemplateCondition; /** * A tag interface for declaring methods that accept objects and convert them into HTML based * on an associated template. Methods return {@link SafeHtml} instances which can be used in many * GWT and GXT widgets to render content. XTemplates support a variety of features to make it easy * to generate content, including: * *
**
* *- Reading properties and nested properties
*- Formatting data into strings
*- Collection and Array iterating, applying sub templates to each item
*- Conditional support, including the ability to call other Java methods that return boolean
*- Basic math and expression support
*
* * Declaring a Template * ** Templates are declared by creating a new interface that extends {@code XTemplate}, or by * extending another interface that extends {@code XTemplate}. Instances can then be created by * invoking {@code GWT.create} on the template class, and then methods can be invoked. *
** Template method content is created in one of two ways: either by declaring the template content * in the {@code @XTemplate} annotation, or by creating a new html file and pointing the * {@code @XTemplate} annotation at that file. *
*public interface SampleXTemplates extends XTemplates { {@literal @}XTemplate("<div>Hello, {name}!</div>") SafeHtml hello(String name); {@literal @}XTemplate(source="hello.html") SafeHtml helloExternal(String name); } private SampleXTemplates tpl = GWT.create(SampleXTemplates.class);
* In this example, {@code tpl.hello("test")} would return a {@code SafeHtml} instance representing * the html *
* while {@code tpl.hello("test")} would have its content depend on the template defined in the file * {@code hello.html} in the same package. * *<div>Hello, test!<div>
-
*
-
* Reading properties
*
* This is the data used for reference in each code sample: *
*public class Kid { public Kid(String name, int age) ... public String getName() ... public int getAge() ... } public class Person { public Person(String name, String company, String product, String location) ... public String getName() ... public String getCompany() ... public String getProduct() ... public String getLocation() ... public List<Kid> getKids() ... public void setKids(List<Kid> kids) ... } final Person person = new Person("Darrell Meyer", "Sencha Inc", "GXT", "Washington, DC"); List<Kid> kids = new ArrayList<Kid>(); kids.add(new Kid("Alec", 4)); kids.add(new Kid("Lia", 2)); kids.add(new Kid("Andrew", 1)); person.setKids(kids);
** Properties are read by naming the object or property to read in {@code { ... }} brackets in the * template body. In the main template (not in a {@code <tpl for="...">} tag) these will be * scoped based on the arguments to the template. If there is only one argument, the argument may * be named, or properties may be referred to directly. If there are multiple arguments, they must * be named. *
*
*interface ReadingPropertiesTemplates extends XTemplates { {@literal @}XTemplate("Hello, {name}, from {person.location}") // either works SafeHtml oneArgument(Person person); {@literal @}XTemplate("Hello, {one.name}, {two.name}, and {three.name}!") SafeHtml twoArguments(Kid one, Kid two, Kid three); } ReadingPropertiesTemplates tpl = GWT.create(ReadingPropertiesTemplates.class); SafeHtml parentContent = tpl.oneArgument(person); SafeHtml childrenContent = tpl.twoArguments(person.get(0), person.get(1), person.get(2));
* Nested properties are read by separating each getter or method call with a '{@code .}'. * Properties are most often read from getter methods, but can also be read from zero-arg methods * by using their full name. As a result of this, the size of the list retrieved from * {@code Person.getKids()} can be expressed as {@code kids.size}: *
*
*interface PersonWithKidsTemplate extends XTemplates { {@literal @}XTemplate("{name} has {kids.size} children") SafeHtml renderChildCount(Person p); } PersonWithKidsTemplate tpl = GWT.create(PersonWithKidsTemplate.class); SafeHtml content = tpl.renderChildCount(person);
* -
* Formatting data into strings
*
*
* Values can be formatted using the following syntax: * *
*-
*
- {@code {value:formatName}} - no format param *
- {@code {value:formatName(format)}} - with format param
*
* Built-in formats: *
-
*
- {@code date(format)} - format syntax uses GWT DateTimeFomat (example: * {@code {mydate:date("m/d/yyyy")})} *
- {@code number(format)} - format syntax uses GWT NumberFormat (example: * {@code {mynumber:number("0000.0000")})} *
- {@code currency} - no parameters *
- {@code scientific} - no parameters *
- {@code decimal} - no parameters * *
* Additional formatters can be created and registered when creating an XTemplate. They can be * declared on any class - when an XTemplates type is declared, it, and all parents will be checked * for formatters to use. Formatters can be redeclared when a type is extended - the type closest to * the final type will override other formatters. * * * *
*
*
* The tpl tag and the for operator are used to
* process the provided data object:
*
-
*
- If the value specified in for is an array, it will auto-fill, * repeating the template block inside the tpl tag for each item in the * array. *
- If for="." is specified, the data object provided is examined. *
- While processing an array, the special variable {#} will provide * the current array index + 1 (starts at 1, not 0). *
<tpl for=".">...</tpl> // loop through array at root node
<tpl for="foo">...</tpl> // loop through array at foo node
<tpl for="foo.bar">...</tpl> // loop through array at foo.bar node
*
* Using the sample data above:
*
*
interface KidListTemplate extends XTemplates {
{@literal @}XTemplate("<p>Kids: " +
"<tpl for='.'>" + // process the data.kids node
"<p>{#}. {name}</p>" + // use current array index to autonumber
"</tpl></p>")
SafeHtml listKids(List<Kid> kids);
}
KidListTemplate tpl = GWT.create(KidListTemplate.class);
SafeHtml content = tpl.listKids(person.getKids()); // pass the kids property of the data object
*
* * An example illustrating how the for property can be leveraged * to access specified members of the provided data object to populate the * template: *
* *
interface NestedListTemplate extends XTemplates {
{@literal @}XTemplate("<p>Name: {name}</p>" +
"<p>Title: {title}</p>" +
"<p>Company: {company}</p>" +
"<p>Kids: " +
"<tpl for='kids'>" + // interrogate the kids property within the data
"<p>{name}</p>" +
"</tpl></p>")
SafeHtml renderPerson(Person person);
}
SafeHtml content = tpl.renderPerson(person);
*
* * * When processing a sub-template, for example while looping through a child * array, you can access the parent object's members via the parent * object: *
* *
interface ParentChildTemplate extends XTemplates {
{@literal @}XTemplate("<p>Name: {name}</p>" +
"<p>Kids: " +
"<tpl for=\"kids\">" +
"<tpl if=\"age > 1\">" +
"<p>{name}</p>" +
"<p>Dad: {parent.name}</p>" +
"</tpl>" +
"</tpl></p>")
SafeHtml renderParentAndChildren(Person person);
}
SafeHtml content = tpl.renderParentAndChildren(person);
*
*
*
*
* The tpl tag and the if operator are used to
* provide conditional checks for deciding whether or not to render specific
* parts of the template. Notes:
-
*
- If quotes are to be used in the conditionals, they must either be different quotes than were * used to define the if, or must be escaped. *
- Greater-than (>) symbols must be escaped within conditionals as > *
- There is no else operator — if needed, two opposite * if statements should be used. *
<tpl if="age > 1 && age < 10">Child</tpl>
<tpl if="age >= 10 && age < 18">Teenager</tpl>
<tpl if="id==\'download\'">...</tpl>
<tpl if="needsIcon"><img src="{icon}" class="{iconCls}"/></tpl>
// no good:
<tpl if="name == "Jack"">Hello</tpl>
// encode " if it is part of the condition, e.g.
<tpl if="name == "Jack"">Hello</tpl>
*
* Using the sample data above:
*
*
interface OlderChildListTemplate extends XTemplates {
{@literal @}XTemplate("<p>Name: {name}</p>" +
"<p>Kids: " +
"<tpl for=\"kids\">" + // either double quotes (escaped)
"<tpl if='age > 1'>" + // or single are allowed
"<p>{name}</p>" + // (no need to escape either in an external file)
"</tpl>" +
"</tpl></p>")
SafeHtml renderFamilyOf(Person person);
);
SafeHtml content = tpl.renderFamilyOf(person);
*
*
*
* The following basic math operators may be applied directly on numeric data
* values:
*
* + - * / ** * To be returned as part of the template, expressions must be contained within {@code {[ ... ]}} * brackets. * *
* For example: * *
interface FutureAgesTemplate extends XTemplates {
{@literal @}XTemplate("<p>Name: {name}</p>" +
"<p>Kids: " +
"<tpl for=\"kids\">" +
"<tpl if=\"age > 1\">" + // <-- Note that the > is encoded
"<p>{#}: {name}</p>" + // <-- Auto-number each item
"<p>In 5 Years: {[age+5]}</p>" + // <-- Basic math
"<p>Dad: {parent.name}</p>" +
"</tpl>" +
"</tpl></p>")
SafeHtml renderFutureChildAges(Person person);
);
SafeHtml content = tpl.renderFutureChildAges(person);
*
interface TemplateUsingEquals extends XTemplates {
{@literal @}XTemplate("<tpl if='o1:equals(o2)'>true</tpl>")
SafeHtml tpl(Object o1, Object o2);
}
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TemplateCondition {
/**
* The name of the method to define. Defaults to the {@link #methodName()}.
*
* @return the name of the method as it will be used in XTemplate source, or "" if the same
* as {@link #methodName()}
*/
String name() default "";
/**
* @return the type the condition method is defined on.
*/
Class> type();
/**
* The name of the method to invoke from a compiled template. This method must exist on
* {@link #type()} or a superclass.
* @return the method to invoke on {@link #type()}
*/
String methodName();
}
/**
* Holds a collection of {@link TemplateCondition} instances, allowing more than one to be
* declared at a time.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TemplateConditions {
TemplateCondition[] value();
}
}