|
|||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||
public interface ComponentXML
By allowing you to keep layout information and property settings in an XML format, Component XML enables non-developers to build and maintain portions of your application, either by editing screens within Visual Builder or by directly editing the XML itself.
Unlike the similar GWT "UIBinder" technology, Component XML does not require a compilation step. XML screen definitions can be generated on the fly, modified at runtime, stored in a database, and in all other ways treated as a dynamic resource. See the section "Dynamic Component XML" for details.
To create a Smart GWT component in XML code, you create a tag with the component's class name. You can set that component's properties either as tag attributes:
<Button title="Click me" width="200" />
or in nested tags:
<Button>
<title>Click me</title>
<width>200</width>
</Button>
To set a property that is an Array of simple types (like int, or String), repeat tags like
so (for colWidths):
<DynamicForm>
<numCols>2</numCols>
<colWidths>250</colWidths>
<colWidths>*</colWidths>
</DynamicForm>
To set a property that takes an Array of complex objects, use the property name as a
container tag, then create further nested tags for the objects in the array, like so (for
fields):
<ListGrid>
<fields>
<ListGridField name="accountName" ... />
<ListGridField name="accountType" ... />
</fields>
</ListGrid>
This same approach works for creating nested layouts, such as placing a ListGrid in a VLayout:
<VLayout>
<members>
<ListGrid .. />
</members>
<VLayout>
Referring to previously defined components
To refer to another component by ID in XML, use <Canvas ref=/>. For example:
<Canvas ID="myCanvas"/>
<Canvas ID="myCanvas2"/>
<VLayout>
<members>
<Canvas ref="myCanvas"/>
<Canvas ref="myCanvas2"/>
</members>
</VLayout>
Save your Component XML as a file called screenName.ui.xml under webroot/shared/ui/. Placing your .ui.xml file in this directory makes it visible to the system; the location of this directory can be configured in server.properties by setting the project.ui property. screenName can be any valid identifier (no spaces, dashes or periods - underscores OK).
If you have multiple top-level tags (eg, your code is similar to the example above under "Referring to previousy defined components") use <isomorphicXML> as a top-level container tag - this has no impact on processing and is just an idiom to make your file valid XML, since XML does not allow multiple top-level tags in a document.
Component XML screens are then loaded using the ScreenLoaderServlet. The default SDK comes
with this servlet already registered at
projectBase/sc/screenLoader. If you've modified web.xml
or only included some of the default servlets, you may need to add it now - see the
Installation Instructions.
To create an application that consists of just the imported mockup, just add a <script src> tag pointing to the ScreenLoader servlet and referring to the screenName you used when you saved your file. For example, add the following to your bootstrap .html file:
<script src="sc/screenLoader?screenName=screenName"></script>
If you want to load screens dynamically, or if you want to load more than one screen, use
RPCManager.loadScreen. See the section
on "Multiple screens and global IDs"
below.
You can retrieve the components in your loaded screen in order to add event handlers to
them, call APIs on them, place them into layouts you programmatically create, and in general
add dynamic behavior. Retrieve the components via the getByID API
(note, when working with multiple screens, be sure to see the upcoming section about managing
global IDs).
You can then add event handlers normally. For example, say there is a ListGrid with ID "mainGrid" and a DynamicForm with ID "editForm" in the same screen, and you want to populate the form with whatever record is clicked on in the grid:
ListGrid grid = (ListGrid)Canvas.getByID("mainGrid");
final DynamicForm form = (DynamicForm)Canvas.getByID("editForm");
grid.addRecordClickHandler(new RecordClickHandler() {
public void onRecordClick(RecordClickEvent event) {
form.editRecord(event.getRecord());
}
});
You can also add a loaded screen to an existing layout container. For example, perhaps you've
already written parts of the application via normal coding techniques, and now you want to take
a screen defined in Component XML and place it in a particular Layout you've already created
("existingLayout" below) - just use Layout.addMember as usual:
existingLayout.addMember(Canvas.getById("componentId"));
A Component XML screen created in Visual Builder or via the
Balsamiq importer will assign global IDs to all
components
generated from your mockup so that you can retrieve them by ID to add event handlers and
call APIs. However if you build an application out of multiple screens built at different
times, these IDs can collide, which will cause components to overwrite each other as they
each try to use the same ID.
To solve this, the RPCManager.loadScreen
API will ignore global IDs on loaded
components, assigning them sequential generated IDs instead (which will never collide). Only
the list of specific global IDs you pass to loadScreen() will be allowed to become
global.
Therefore when building an application out of multiple screens, the best approach is:
loadScreen(), pass the list of IDs of components that you will
need to access programmatically
There are two additional ways to load Component XML screens - you can create a .jsp that uses the JSP tags that come with the SDK:
<%@ taglib uri="/WEB-INF/iscTaglib.xml" prefix="isomorphic" %>
<isomorphic:XML>
... Component XML ...
</isomorphic:XML>
Or you can use the server-side API com.isomorphic.XML.toJS():
XML.toJS("<isomorphicXML xmlns:xsi=\"nativeType\">" +
componentXMLCode +
"</isomorphicXML>");
The JSP code above and the programmatic call to XML.toJS() both return a JavaScript code,
which is the response that RPCManager.loadScreen expects. The
XML.toJS() API can be easily combined with
direct use of the server-side
DataSource API to build
a version of the ScreenLoaderServlet that can retrieve Component XML from a database
or any Java API.
For static Component XML screens (cannot be changed at runtime), you can optionally run the
XML.toJS() process as a build step to save a small amount of runtime overhead in XML to JS
translation. Use RPCManager.loadScreen
to load the resulting JavaScript by
overriding the actionURL to point to
the generated JavaScript file.
Note that the overhead is minor enough that this is not worth doing unless you have a very
large deployment and a very large number of static Component XML files.
XML parsing errors, which happen when XML is not well-formed and would be rejected by any standard XML parser, are reported in the server-side log, and, when possible, also in the client-side log within the "Results" tab of the Developer Console.
If you are loading a screen via the RPCManager.loadScreen API, you can see the
response from the server in the RPC tab of the Developer Console - this will show you issues
such as a misplaced ScreenLoaderServlet (HTTP response code will be 404 - Not Found) or
responses that contain server exception details instead of the expected JavaScript response.
You can also use the "Eval XML" section in the "Results" tab of the Developer Console to interactively experiment with Component XML ("Eval XML" button) and as a means of seeing the generated JavaScript ("Show JS" button).
Component XML files support embedding references to messages loaded from ResourceBundles via
the same JSTL-like <fmt> syntax as is used for DataSource .ds.xml files. See
DataSource localization for details.
|
|||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||