Table of Contents
[fleXive] offers a set of JSF components for working with [fleXive] contents and data structures. This includes components to render and edit FxContent instances, submit search queries and show their results, and create custom content queries. To make your own reusable components, [fleXive] provides a simple-to-use plugin API for wiring your own reusable JSF and EJB components for other [fleXive] applications.
[fleXive] JSF support consists of two major modules:
The JSF component library contains a set of JSF components for working with [fleXive] structures in any JSF application
The JSF plugin API allows applications or plugins to extend the administration GUI and make themselves extensible.
A comprehensive guide on extending [fleXive] functionality is the section called “Writing reusable [fleXive] components ”.
To use the [fleXive] component library, you have to
Add flexive-plugin-jsf-core.jar to your application's classpath
Add the namespace declaration
xmlns:fx="http://www.flexive.com/jsf/core"
to the top of your XHTML documents.
On every page using [fleXive] components, you have to add a call to <fx:includes/> somewhere in the HTML head section. This tag includes javascript files and CSS stylesheets needed by the components via Weblets.
If you want to use components based on Yahoo UI, you have to include a call to
<fx:yuiSetup/>
near the end of the HTML body section. This initializes all YUI components
on the current page and loads the required Javascript libraries.
You also have to specify the YUI skin class on your page, the most convenient way
is through the body tag, e.g.:
<body class="yui-skin-sam">
.
The [fleXive] components for displaying and editing contents are most crucial for any application that works with [fleXive] contents.
The
<fx:content>
component offers direct access to FxContent values through the property XPath.
It also supports groups and multiplicities, i.e. iteration over properties and groups that
may exist more than once in an instance.
When no content ID is specified, a FxType name or ID is passed to create a fresh instance
of the given property type. Instances can then be saved through the
fxContentViewBean,
or any other JSF managed bean that has a FxContent property.
<fx:content var="varname" (pk="pkexpr" | type="typeId" | typeName="typeName") [preserveContent="true|false"]> ... </fx:content>
The name of the variable that provides the content. The actual FxContent instance itself is provided in "#{var}_content", i.e. if var="project", then the FxContent is supplied in "project_content".
A primary key. May be supplied as an FxPK object, a long ID, a String containing a primary key (e.g. "5", "5.1", "5.MAX"), a FxReference, or a FxSelectListItem whose ID will be interpreted as a content ID.
The new content type ID (if no PK was specified)
The new content type name (if no PK was specified)
The content instance to be displayed (if no PK was specified).
If set to true, the content instance will be stored in the JSF viewstate. This is memory-expensive, but is necessary for editor pages that modify the content structure, e.g. pages that allow to add or remove groups or properties. By default, this option is set to false.
A main service of the
<fx:content>
component is to
provide direct access to the property values stored in FxContent instances
through JSF-EL expressions. Inside the body of
<fx:content var="content">
,
the following expressions may be used:
#{content.name}
,
#{content['name']}
,
#{content['/name']
Return the FxValue of the property identified by the XPath "/name[1]".
For properties like "/name" that are attached directly to the content root node, the
notations
#{content.name}
,
#{content['name']}
, and
#{content['/name']}
are
equivalent. The following examples won't always specify all possible notations.
#{content.name$label}
Return the assignment label of type FxString for the given XPath.
#{content.name$hint}
Return the assignment hint of type FxString for the given XPath.
#{content['group/text']}
Return the given group property. Note that
#{content.group.text}
currently does not work.
#{content.element$list}
Provide a list for all entries of the group (or property) "element". If "element" is
a
property, the iterator returns FxValue objects, otherwise it returns a
list of virtual fx:content instances with a prefix for the current group element
(
Example 7.1, “Render FxContent property values”
illustrates how this feature
can be used for looping over groups with
<ui:repeat>
).
#{content.element$listAll}
Like
#{content.element$list}
, but includes empty elements.
#{content.reference$.property}
Resolve the given reference property and provides a content for its properties. An
expression can also use several nested resolving operations, e.g.
#{content.reference$.owner$.email}
.
#{content['group/text$new']}
Create a new instance of "group" and return its text property. Note: the current implementation is a hack and works only for simple cases.
#{content['group/text$mayCreateMore']}
Returns true if evaluating the $new suffix for the given XPath will succeed. Useful when using the $new suffix for assignments with a limited multiplicity, since it could cause an exception otherwise.
#{content.name$valid}
Return true if the given XPath (name) is valid for the content instance.
Be aware that
<fx:content>
is a render-time component. That is, the content instance is
provided during view rendering (i.e. between encodeBegin and encodeEnd), but not during view
creation. This means, unfortunately, that it is not possible to use Facelets' compile-time
tags like
<c:forEach>
or
<c:if>
with EL expressions that contain content instances provided by
<fx:content>
.
Instead, render-time components must be used to achieve similar results - for example,
<ui:repeat>
to iterate over lists or
<ui:fragment rendered="...">
for conditional page rendering.
Example 7.1. Render FxContent property values
Here the primary key is provided by the managed bean "myBean". The content is stored in the request variable "component".
<fx:content pk="#{myBean.pk}" var="component"> Component: #{component.name} <br/> <!-- Resolve a content reference to a project content with $ --> Assigned project: #{component.project$.name} (PK = #{component.project})<br/> <!-- Iterate over all elements of the "comment" group with $list --> <ui:repeat var="comment" value="#{component.comment$list}"> <h5>Comment by #{comment.author$.caption} on #{comment.created_at}:</h5> <p>#{comment.text}</p> </ui:repeat> <!-- Access via full XPath --> #{component['/comment[5]/author$.caption']} </fx:content>
Example 7.2. Edit an existing FxContent instance
We use the
<fx:value>
component to create an input field for the "name" property of a given instance.
<a4j:form id="frm"> <fx:content pk="#{myBean.pk}" var="component"> <!-- Render an input row for the "name" property of the enclosing content tag --> <fx:value property="name"/> <!-- Save content using the FxContentViewBean, pass the content instance stored in component_content" via f:setPropertyActionListener --> <h:commandButton action="#{fxContentViewBean.save}" value="Create component"> <f:setPropertyActionListener target="#{fxContentViewBean.content}" value="#{component_content}"/> </h:commandButton> </fx:content> </a4j:form>
Example 7.3. Create a new FxContent instance
This page provides a basic input form for creating new instances of the "Component" type. Note that a new content instance contains empty values for all basic properties - that's why this example works. For creating a more complex instance that actually creates new properties, see the next example. Note that this code is basically the same as Example 7.2, “Edit an existing FxContent instance”, except that a typename is passed instead of a PK - there's no difference in code between editing an existing or a new instance (provided that the latter has been properly initialized with empty values).
<a4j:form id="frm"> <fx:content id="componentView" typeName="Component" var="component"> <!-- Render an input row for the "name" property of the enclosing content tag --> <fx:value property="name"/> <!-- Save content using the FxContentViewBean, pass the content instance stored in "component_content" via f:setPropertyActionListener --> <h:commandButton action="#{fxContentViewBean.save}" value="Create component"> <f:setPropertyActionListener target="#{fxContentViewBean.content}" value="#{component_content}"/> </h:commandButton> </fx:content> </a4j:form>
Example 7.4. Add values to properties with multiplicities
Assume type "issue" has a group "comment" with multiplicity 1..n. In order to edit existing instances, you could iterate over the existing using the $list suffix. For creating a new "comment" group, you specify the XPath without multiplicities and set the "new" attribute.
<a4j:form id="frm"> <fx:content pk="#{myBean.pk}" var="issue"> <!-- Enter a new comment --> <fx:value property="comment/text" new="true"/> <!-- Save button etc... --> </fx:content> </a4j:form>
Example 7.5. Add a new empty group to a content instance
Assume you're editing a contact data type with a group named ContactPerson. You want to render editors for all existing contact persons, as well as an empty one for adding new contacts. This is accomplished with the fxContentViewBean which has a method for creating new empty elements or groups called "add".
<!-- Specify preserveContent="true" to keep structural changes made to the content instance --> <fx:content pk="#{myBean.pk}" var="data" preserveContent="true"> <!-- Show editors for all existing contact person groups stored under the XPath /contactPerson --> <ui:repeat var="contactPerson" value="#{data.contactPerson$listAll}"> <fx:fieldSet legend="Contact Person"> <fx:value var="contactPerson" property="name"/> <fx:value var="contactPerson" property="email"/> </fx:fieldSet> </ui:repeat> <!-- Render a button to add a new contact person group to the "data" content instance --> <h:commandButton action="#{fxContentViewBean.add}" value="Add another person"> <!-- Pass the content instance to the JSF bean --> <f:setPropertyActionListener value="#{data_content}" target="#{fxContentViewBean.content}"/> <!-- Specify the XPath of the element to be added --> <f:setPropertyActionListener value="/CONTACTPERSON" target="#{fxContentViewBean.xpath}"/> </h:commandButton> </fx:content>
Example 7.6. Use InputMappers for application-specific properties
Some content properties cannot be populated in a generic way. InputMappers wrap the FxValue provided by the content instance in another FxValue, for example a FxSelectOne select item value.
<a4j:form id="frm"> <fx:content pk="#{myBean.pk}" var="issue"> <!-- Provide a list of contents for this reference property --> <fx:value property="owner" inputMapper="#{myBean.accountMapper}"/> <!-- Save button etc... --> </fx:content> </a4j:form>
In this very basic implementation the input mapper is constructed from a collection of PKs returned by our business method "someOtherBean.getAccountPks()". There already exists an input mapper for FxPK objects in the flexive framework that takes a select list and interprets the item IDs as PK IDs. A "real" input mapper would probably use less generic labels and use the account caption instead.
public class MyBean { public InputMapper getAccountMapper() { FxSelectListEdit selectList = new FxSelectList("Accounts").asEditable(); for (FxPK pk: someOtherBean.getAccountPks()) { new FxSelectListItem(pk.getId(), selectList, -1, "Account " + pk); } return new FxPkSelectOneInputMapper(selectList); } }
The
<fx:children>
component provides an iterator over properties and groups of a content instance.
The current value is stored in a variable with the same name as the property.
The same can be achieved by using the
$list
JSF-EL suffix as described in
the section called “Accessing property values with JSF-EL”.
<fx:content ...> <fx:children value="content" property="xpath" [var="varname"]> ... </fx:children> </fx:conent>
The name or XPath of the property or group to be iterated upon.
The content or group value holding the required property.
Name of the variable where the current value will be exposed in the tag body. If not set, the property name will be used (i.e. the last part of the given property XPath).
Note: due to its implementation, if a
fx:children
component is nested in another
fx:children
that has a var attribute, the inner
fx:children
instance also must specify the var attribute.
If empty elements should be included (default: false).
The following examples are based on the products demo application described in an ONJava.com article.
Example 7.7. Iterating over property values
In this example, we iterate over the
image
property of a product. The property is of type
Binary
and holds one or more images for the given product.
<fx:content var="product" pk="#{productBean.pk}"> <fx:children value="#{product}" property="image"> <fx:thumbnail binary="#{image}"/> </fx:children> </fx:content>
Example 7.8. Iterating over group values and nested iterators
In this example, we create an outer loop for the group property
variant
and use a nested
<fx:children>
component to render the images for each group.
Data structure (partial):
<fx:content var="product" pk="#{productBean.pk}"> <!-- Iterate over the "variant" group of product --> <fx:children value="#{product}" property="variant"> <!-- Iterate over the "image" property of the current variant --> <fx:children value="#{variant}" property="image"> <fx:thumbnail binary="#{image}"/> </fx:children> </fx:children> </fx:content>
The
<fx:contentEditor>
component allows creation, editing and deletion of content instances
similar to the Instance Editor.
<fx:contentEditor editorId="editorId" formPrefix="formPrefix" (contentId="contentId" | pk="pkexpr" | content="contentExpr" | typeId="typeId" | type="typeExpr") [var="varname"] [valueFormatter="valueFormatterExpr"] [reset="true|false"] [reRender="clientId"] [editMode="true|false"] [disableAcl="true|false"] [disableWorkflow="true|false"] [disableEdit="true|false"] [disableDelete="true|false"] [disableVersion="true|false"] [disableCompact="true|false"] [disableSave="true|false"] [disableCancel="true|false"] [disableButtons="true|false"] [disableAddAssignment="true|false"] [disableRemoveAssignment="true|false"] [disablePositionAssignment="true|false"] [disableMessages="true|false"] [showLockOwner="true|false"]> ... </fx:contentEditor>
Id of the content editor component (must be unique in a view, used as key to retrieve a specific content instance stored in view-state).
The form prefix of the surrounding form.
Id of the content to be edited. The maximum available version is loaded.
FxPk of the content to be edited.
Content instance to be edited.
Type id of the content instance to be created.
FxType of the content instance to be created.
Variable name to expose the FxWrappedContent instance within the tag's body.
Useful if you want to extend the component's functionality.
See the section called “Customizing the <fx:contentEditor>
component” for details.
A custom valueFormatter which is passed to <fx:fxValueInput/> components within this component.
True if the content for the given editor id should be
reset upon the next request
(==removed from content storage and reinitilaized with
given attributes, default: false). Normally you won't use this, but
if you want to know more, see the section called “Customizing the <fx:contentEditor>
component”
for details.
External client id which is to be rerendered upon the next AJAX-request triggered by the content editor component. Normally you won't use this, unless you need to rerender a component containing several fxContentEditors.
If true initilaizes this component to edit mode, otherwise to view mode (default: false).
True if ACL selectbox should not be rendered (default:false).
True if workflow selct box should not be rendered (default:false).
True if "edit" button should not be rendered (default:false).
True if "delete" button should not be rendered (default:false).
True if "save in new version" button and "delete version" button should not be rendered (default:false).
True if "compact" button should not be rendered (default:false).
True if "save" button should not be rendered (default:false).
True if "cancel" button should not be rendered (default:false).
True if no buttons should be rendered (default:false).
True if icons for adding/inserting assignments should not be rendered (default:false).
True if icons for removing assignments should not be rendered (default:false).
True if icons for positioning assignments should not be rendered (default:false).
True if the <h:messages/> tag inside the content editor should not be rendered (default:false).
True if the inline editor controls for references should not be rendered (default: false).
A JavaScript code which is called when the editor is closed (clicking on the "Save and exit" or "Stop editing" button)
True if the the respective content's lock owner should be shown (default: true).
Because of its generic nature the content editor cannot satisfy every need out of the box. However, precautions have been taken to make this component customizable to your specific application needs. Let's look at the different parts that make up the content editor more closely:
All relevant style entries are prefixed with .fxContentEditor_
.
So if you want to replace icons and images, change colors etc., you can
include your own stylesheet overriding those entries.
<ui:insert>
tags allow you
to insert or replace whole parts of the content editor component
via <ui:define>
.
The provided names of the <ui:insert>
tags and respective locations are:
FxWrappedContent is a wrapper class for FxContent instances
that provides convenience methods for JSF-handling. By providing
a variable name you can expose that wrapper class and access it via JSF-EL
or inject it into your own custom beans via the
<f:setPropertyActionListener/>
tags.
See [fleXive] JavaDoc for further details about that class.
By using templating and FxWrappedContent as described above you can add your own buttons to add additional functionality. Also you may extend existing functionality by calling methods of the component's backing bean FxContentEditorBean from within your own managed beans. See the section called “Content Editor Examples” for examples and important instructions.
Example 7.9. Content Editor simple usage
Here you see a simple usage examples, together with necessary "surroundings" when using this component. Don't forget that Ajax4jsf and MyFaces Tomahawk tag libraries are also required.
<head> <!-- necessary flexive includes --> <fx:includes all="true"/> </head> <!-- skin for yui based components --> <body class="yui-skin-sam"> <!-- prefixed multipart form --> <h:form id="frm" enctype="multipart/form-data"> <!-- content editor for editing the content with id 16 --> <fx:contentEditor contentId="16" editorId="editor1" formPrefix="frm"/> <!-- content editor for creating a new content with the given type id --> <fx:contentEditor typeId="3" editorId="editor2" formPrefix="frm"/> <!-- content editor for editing a given content --> <fx:contentEditor content="#{myBean.myContent}" editorId="editor3" formPrefix="frm"/> <!-- necessary yuiSetup tag --> <fx:yuiSetup/> </h:form> </body> </html>
Example 7.10. Content Editor adding buttons
In this example three buttons are added, which will be inserted in the contentEditor component's template at the <ui:include/> named "additionalButtons". Note that for the Ajax4jsf button flexive.contentEditor.preSubmit() should be called. If you want to use actions of the component's backing bean, make sure you set up the property action listeners accordingly.
<fx:contentEditor var="myContent" ...> <ui:define name="additionalButtons"> <!-- adding a command button --> <h:commandButton value="My Button" action="#{myBean.doSomething}"> <!-- property action listener for FxWrappedContent--> <f:setPropertyActionListener value="#{myContent}" target="#{myBean.content}"/> </h:commandButton> <!-- adding an ajax command button --> <a4j:commandButton value="My Ajax Button" action="#{myBean.doSomething}"> <!-- necessary js call when using a4j button(caused by a4j multipart form submit bug --> onclick="flexive.contentEditor.preSubmit();" <!-- rerender attribute --> reRender="#{myContent.guiSettings.reRender}" <!-- using the content editor component's status --> status="#{myContent.editorId}_status"> </a4j:commandButton> <!-- adding property action listeners for the component's backing bean (FxContentEditorBean)--> <a4j:commandButton .. action="#{__ceBean.action}"> <f:setPropertyActionListener value="#{myContent.editorId}" target="#{__ceBean.editorId}"/> <f:setPropertyActionListener value="#{myContent.guiSettings.reRender}" target="#{__ceBean.reRender}"/> </a4j:commandButton> </ui:define> </fx:contentEditor>
Example 7.11. Content Editor calling the backing bean
In this example the backing bean is retrieved, an action is called and finally the component tree is reset. Resetting the component tree is important if the tree structure changes in between requests, so it can be constructed anew when the page is rendered. This is necesarry if for example elements change place or are deleted in order to avoid duplicate id errors. Make sure you have set up the actionlisteners accordingly as described in Example 7.10, “Content Editor adding buttons” when calling methods of the backing bean.
import com.flexive.faces.beans.FxContentEditorBean; import com.flexive.faces.FxJsfUtils; import com.flexive.faces.components.content.FxWrappedContent; import com.flexive.faces.messages.FxFacesMsgErr; public String myAction() { // get the content edtior bean FxContentEditorBean editor = (FxContentEditorBean)FxJsfUtils.getManagedBean("fxContentEditorBean"); // Retrieve the wrapped content FxWrappedContent content = editor.getContentStorage().get(editor.getEditorId()); try { // calling a method editor._save(false); } catch (Throwable t) { new FxFacesMsgErr(t).addToContext(); } finally { // delete the component tree to avoid duplicate id errors FxJsfUtils.resetFaceletsComponent(content.getGuiSettings().getFormPrefix() + ":" + content.getEditorId()); } // action outcome return null; }
For writing FxContent editors, the
<fx:value>
component provides a complete property value input row consisting of
the assignment label translated in the current user's locale, and
a
<fx:fxValueInput>
instance that renders suitable input tags for all supported data
types, including multilanguage and binary support.
The output is controlled by the
<fx:formRow>
component.
All parameters of
<fx:formRow>
can also be set for
<fx:value>
, except those that control the actual value being
rendered.
Note:
<fx:value>
is a Facelets compile-time component, this means that its input variables must be bound during
view creation. Data exposed by components like
<ui:repeat>
is not available during "compile time" and cannot be used as input for
<fx:value>
. Use compile-time iterators such as
<c:forEach>
instead.
<fx:value property="xpath" [var="varname"] [labelKey="messagekey"] [any attribute for fx:formRow]/>
The XPath of the property.
The value of the "var" attribute of the
<fx:content>
component whose content should be edited. If nested directly in a
fx:content tag, this attribute can be omitted.
An optional label that overrides the assignment label.
An optional message key that overrides the assignment label.
The input label tooltip (optional).
Message key of the tooltip (overrides tooltip, if not specified and labelKey is set,
it defaults to#{labelKey}.tooltip
)
If true, no input field will be rendered.
For multiline and HTML properties, force to render a single-line input field (e.g. for search query forms).
An optional input mapper for rendering the input control. For example, properties referencing other content may need a custom input mapper that provides a select list of content instances. For more information take a look at the InputMapper documentation and at Example 7.6, “Use InputMappers for application-specific properties”.
A
FxValueFormatter
to be used for rendering the value (in read-only mode only). If not specified,
the JSF renderer will choose the appropriate default formatter for
the actual value class.
If set to false, HTML output will not be filtered. If set to true (the default), HTML entities will be used for sensitive characters (e.g. "<" instead of "<").
Disables multi language support even if the FxValue object is multilingual. Only the default translation will be displayed and updated.
Set this property to true if the Lytebox javascript library used for rendering inline previews of images should not be used.
An optional javascript expression to be called when an input element changed its value.
An instance of the
flexive.yui.AutoCompleteHandler
javascript class. This class provides a query method for a
client-side autocomplete widget provided by Yahoo UI, as well as a method
for formatting the response.
For basic usage examples, look at the
the section called “Examples”
in the
<fx:content>
documentation.
For examples on controlling the output of the
<fx:formRow>
component, see
the section called “Examples”
of that component.
The
<fx:fxValueInput>
component is a universal
component for editing FxValue objects. It supports every datatype of FxValue,
for example plain text, numbers, dates, or even binaries. It is used in the
administration GUI content and search query editors and in every other place
where a FxValue needs to be edited. It also includes multilanguage support
by providing a language select list next to the input elements.
The default input language of multi-language values can be set in the
user preferences
of the administration GUI or programmatically through the user configuration parameter
com.flexive.shared.configuration.SystemParameters.USER_DEFAULTINPUTLANGUAGE
.
Note that this component is a JSF UIInput component, thus it supports many standard JSF input facilities (like value change listeners or validators).
<fx:fxValueInput value="fxvalue" [id="clientid"] [externalId="externalId"] [readOnly="true|false"] [readOnlyShowTranslations="true|false"] [forceLineInput="true|false"] [inputMapper="inputMapper"] [valueFormatter="valueFormatter"] [filter="true|false"] [containerDivClass="CSS class"] [disableMultiLanguage="true|false"] [disableLytebox="true|false] [onchange="onchange"] [autocompleteHandler="handler instance"]/>
An expression of type FxValue of the value to be edited. Note that the value must not be null, otherwise the input component cannot determine the actual FxValue type.
An optional client ID of the input component.
An optional external ID that overrides the clientId in JSF validation error messages - may be necessary in complex, generic forms, but usually you won't need this.
If true, only the value itself will be rendered.
If true, all translations of a property will be shown, else only the best matching translation (in the calling users language or the language marked as default).
For multiline and HTML properties, force to render a single-line input field (e.g. for search query forms).
An optional input mapper for rendering the input control. For example, properties referencing other content may need a custom input mapper that provides a select list of content instances. For more information take a look at the InputMapper documentation and at Example 7.6, “Use InputMappers for application-specific properties”.
A
FxValueFormatter
to be used for rendering the value (in read-only mode only). If not specified,
the JSF renderer will choose the appropriate default formatter for
the actual value class.
If set to false, HTML output will not be filtered. If set to true (the default), HTML entities will be used for sensitive characters (e.g. "<" instead of "<").
If this CSS class property is set, the component will be embedded in a div-container using this CSS class as style.
Disables multi language support even if the FxValue object is multilingual. Only the default translation will be displayed and updated.
Set this property to true if the Lytebox javascript library used for rendering inline previews of images should not be used.
An optional javascript expression to be called when an input element changed its value.
An instance of the
flexive.yui.AutoCompleteHandler
javascript class. This class provides a query method for a
client-side autocomplete widget provided by Yahoo UI, as well as a method
for formatting the response.
A JSF listener that is invoked when the component value changes.
Example 7.13. An autocomplete handler for user names
In this example, we use the predefined JSON/RPC autocomplete provider AutoCompleteProvider#userQuery(String query). It searches for user account names based on the user input and returns possible matches.
<script type="text/javascript"> <!-- // Initialize the Javascript handler that submits the queries via JSON/RPC and evaluates the response var userAcHandler = new flexive.yui.AutoCompleteHandler(function(query) { // execute JSON/RPC call and evaluate the response return eval("(" + flexive.util.getJsonRpc().AutoCompleteProvider.userQuery(query) + ")"); }); //--> </script> <fx:fxValueInput value="#{backingBean.userName}" autocompleteHandler="userAcHandler"/>
The backing bean property
#{backingBean.userName}
is a property of type
FxString
and will hold the submitted user name.
Example 7.14. Writing custom autocomplete handlers
An autocomplete provider returns its response to a query in a twodimensional Javascript array. An entry consists of:
The value that will be set in the text input (index: 0).
The displayed label in the autocomplete box, possibly including markup (index: 1).
The Javascript class
flexive.yui.AutoCompleteHandler
provides a small wrapper that is used by the fxValueInput component. To implement
a custom wrapper you need to overwrite the
query
method and perform the autocomplete query inside. This can (but does not have to)
include a server call, e.g. using JSON/RPC. In this example, we define a new query
function that automatically generates "suggestions" based on the input value
by appending a suffix:
<script type="text/javascript"> <!-- var customHandler = new flexive.yui.AutoCompleteHandler(function(query) { var q = decodeURIComponent(query); return [[q + "/a", q + ": <i>a label</i>"], [q + "/b", q + ": <i>b label</i>"], [q + "/c", q + ": <i>c label</i>"]]; }); //--> </script> <fx:fxValueInput value="#{backingBean.fxStringValue}" autocompleteHandler="customHandler"/>
Provides a select list that switches the input language of all
<fx:fxValueInput/>
components on the current page. This tag is implemented in JavaScript,
and it does not cause an extra round-trip to the server.
The resultValue tag is a specialized wrapper for the
<fx:fxValueInput>
to be used for rendering a column value of a search result row.
If the value passed is an instance of
FxValue
, a read-only instance
of
<fx:fxValueInput>
is created which then renders the given value.
Otherwise (e.g. for
FxPK
primary keys or primitive values)
a generic formatter is used, which can be customized e.g. for formatting
of tree paths with a link formatter.
<fx:resultValue value="value" [linkFormatter="formatter"] [itemLinkFormat="format"] [contentLinkFormat="format"]/>
The value to be rendered. Can be of any type.
A
ContentLinkFormatter
instance that will be used for rendering links to contents.
This applies to the rendering of the virtual properties
@pk
and
@path
, as described in
the section called “Tree Search”.
If not specified, the default
ContentLinkFormatter
will be used. For a description of the supported link format,
please refer to the [fleXive] JavaDoc of this class.
The format string passed to the linkFormatter for content links, i.e.
FxPK
values. For a description of the supported link format of the default formatter,
please refer to the [fleXive] JavaDoc of this class.
The format string used for
FxPaths
values as returned by the virtual
@path
property. For a description of the supported link format of the default
formatter,
please refer to the [fleXive] JavaDoc of this class.
A basic example of using
<fx:resultValue>
can be found in
the section called “Tutorial 1: The Document Store Application”.
Iterates over a collection of content instances. This component is essentially an iterator wrapping a fx:content component. The content instances can be specified through nested Groovy queries or a SqlQueryBuilder instance.
<fx:contentList var="varname" [indexVar="indexVarName"] [queryBuilder="queryBuilderExpr"] [explode="true|false"]> [<f:facet name="groovyQuery"> ... </f:facet>] [<f:facet name="header"> ... </f:facet>] [<f:facet name="empty"> ... </f:facet>] ... </fx:contentList>
Name of the variable that provides the content. The actual FxContent instance itself is provided in "#{var}_content", i.e. if var="project", then the FxContent is supplied in "project_content".
Optional name for a variable that exposes the current iteration index.
An expression of type SqlQueryBuilder that is used for selecting the contents.
Indicates whether the content instances should be "exploded", i.e. whether empty properties should be initialized. Useful for content editors. Defaults to false.
Embeds a query using FxQueryBuilder directly in the HTML page. For example:
<f:facet name="groovyQuery"> like("caption", "A%") type("myArticleType") </f:facet>
An optional header row. Rendered only if at least one content instance is available.
An optional empty message. This is the only output that is rendered if the query returns no contents, and if no "empty" facet is specified, nothing is rendered at all.
Renders a thumbnail for a given
FxPK
or
FxBinary
reference.
The primary key of the content instance. If the PK is specified, the default thumbnail of the content is rendered.
A specific binary entry of type
FxBinary
to be rendered. This is useful for for content types with more than one binary
property. For an example, see
the section called “
<fx:children>
”.
If true, only the thumbnail URL will be rendered (relative to the context root,
e.g.
thumbnail/pk5.1/s0
).
The desired size of the thumbnail. Valid values are taken from BinaryDescriptor.PreviewSizes:
PREVIEW1
,
PREVIEW2
(default),
PREVIEW3
,
SCREENVIEW
,
ORIGINAL.
If set to
max
or
live
,
it overrides the version information in the PK or binary descriptor.
Renders a Yahoo UI datatable widget for a [fleXive] result set. This provides an easy way of rendering a result to the user, and it includes a paginator widget.
<fx:resultTable var="name" value="query" [viewType="list|thumbnails"] [clickHandler="clickHandler"] [actionColumnHandler="handler"] [previewSize="previewSize"] [rowsPerPage="rowsPerPage"] [initialPage="initialPage"]/>
The name of the Javascript variable that exposes the Yahoo UI DataTable widget.
The result set to be rendered, or a plain text FxSQL query. The following types are supported:
String
A FxSQL query, for example:
SELECT @pk, #image/caption
com.flexive.shared.search.FxResultSet
The result of a FxSQL query.
com.flexive.shared.search.query.SqlQueryBuilder
A FxSQL query builder instance the will be used for fetching the result set.
The view type of the datatable. "list" renders a common table view for each of the columns, while "thumbnails" renders only the thumbnails as in the backend administration's thumbnail view. Note that the thumbnail view only works if the object's primary key ("@pk") was selected in the query, otherwise no valid thumbnail image can be rendered.
An optional Javascript method for handling clicks on the table with
signature
function handler(targetEl, pk)
.
The primary key parameter is only available if the @pk column
was selected in the FxSQL query.
An optional instance of type
flexive.yui.datatable.ActionColumnHandler
for generating the contents of the "Action" column - an additional column that can
be used for displaying custom actions for contents and that will only be visible
when this parameter is set. The
flexive.yui.datatable.ActionColumnHandler#getActionColumn
method is passed the primary key and the permissions of the column, which can be
null if the search result does not contain the @pk or @permissions properties.
name of the preview size to be used for thumbnails (see BinaryDescriptor#PreviewSizes ).
current value for the paginator (optional).
current page index for the paginator (optional).
index of the first column to be included in the table (1-based, optional).
Example 7.15. Using fx:resultTable to submit and render FxSQL queries
The following code snippet renders two result tables: the first in thumbnail mode,
the second in list mode. The query is formulated in FxSQL and is passed using the
value
attribute.
<fx:resultTable var="thumbnailsTable" value="SELECT @pk, #image/caption" viewType="thumbnails"/> <fx:resultTable var="listTable" value="SELECT *"/>
Provides support for updating a result table after an Ajax request. This allows to combine Ajax4jsf with the client-side fx:resultTable widget. After an Ajax response was rendered, this tag updates a result table with the current result values. Take a look at the backend administration's search results page for a more sophisticated example.
The name of the javascript variable that exposes the Yahoo UI DataTable widget.
The result set to be rendered, or a plain text FxSQL query - see <fx:resultTable> documentation.
name of the preview size to be used for thumbnails (see BinaryDescriptor#PreviewSizes ).
index of the first column to be included in the table (1-based, optional).
Example 7.16. Updating a resultTable through an Ajax4jsf update
When re-rendering this Ajax4jsf output panel (e.g. through a command button or an onchange listener) the result table of the given name will be refreshed based on the current result:
<a4j:outputPanel id="refreshResults"> <fx:resultTableUpdater var="resultTable" value="#{fxSearchResultBean.result}"/> </a4j:outputPanel> <!-- Render the result table (this part of the page should not be included in the Ajax response) --> <fx:resultTable var="resultTable" value="#{fxSearchResultBean.result}"/>
A color picker based on Yahoo UI, shown in a popup dialog. The color value will be written to the given form element (a text or hidden input element). The color picker can be nested directly in a JSF input element (e.g. h:inputText). In this case it will be rendered directly before the actual input element.
ID of the input element where the picked color value will be stored. If not set, the parent component ID will be used.
Example 7.17. Using the color picker with a JSF input component
In this example, an existing JSF text input component will be augmented with a color picker.
<h:inputText id="color" value="#{myBean.color}" size="7"> <fx:colorPicker/> </h:inputText>
Example 7.18. Using the color picker for a form input
The color picker can be used "stand-alone" for any text-based form input.
To do so, just set the form input element ID with the
inputId
parameter.
<input type="text" id="myinput" size="7"/> <fx:colorPicker inputId="myinput"/>
Helper tag to linearize the navigation between all fx:fxValueInput instances on a page. After activating the first input on the page, the user can navigate to all following using the "tab" key (i.e. the tabindex will be strictly increasing for all succeeding inputs, skipping other navigation elements and the language selects).
This tag requires Yahoo UI. Add this near the end of the page, but before the call to fx:yuiSetup.
[fleXive] offers a powerful way for mapping web page navigation structures through its tree engine. The components in this section allow rendering of (parts of) the tree in HTML, e.g. web page menus or trees.
Renders part of the content tree as nested
<ul>
elements. These can be styled via CSS to resemble menus or even pop-up menus, or enhanced with
JavaScript using YahooUI components.
<fx:navigation var="varname" [output="default|csspopup|yui"] [path="/treepath"] [mode="live|edit"] [depth="int"] [selectedNodeId="nodeId"] [baseTypeId="id"] [baseTypeName="typename"] [includeRoot="true|false"] [includeFolders="true|false"]> <f:facet name="item"> <ui:fragment> <a href="/content/#{node.id}">#{node.label}</a> </ui:fragment> </f:facet> </fx:navigation>
The variable name where the current tree node of type FxTreeNode will be exposed to the page.
The output format.
Plain HTML output.
Renders additional CSS classes that will show only the first tree level and open the subfolders when the mouse hovers over them.
Renders additional markup that allows the Yahoo UI Menu component to build a menu. If JavaScript is disabled, the plain HTML markup is shown to the use. Note that you have to include YUI on the page with <fx:includes>.
The tree folder to be rendered. If none is specified, the root folder ("/") is rendered.
The tree mode, "edit" or "live" (default).
The maximum tree depth for sub folders. For example, a value of 2 will render content of the given tree path and the first level of subfolders.
If specified, the given tree node ID will be highlighted in the HTML output.
An optional type filter for the rendered nodes. Only nodes whose reference is of the given type (or a subtype of the given type) are rendered.
When a non-folder base type is specified, folders are (by default) not
rendered in the response. You can override this by setting the
includeFolders
attribute.
When
baseTypeId/baseTypeName
is set, setting this attribute to "true" will include folders
and their contents in the output even if the specified base type
is not a folder.
When set to true, the root node of the rendered (sub-)tree is included in the output. (default: false)
Example 7.19. A JSF/HTML navigation that selects the clicked node
<fx:navigation var="node" path="/" depth="5" selectedNodeId="#{navigationBean.selectedNodeId}"> <f:facet name="item"> <h:commandLink> <f:setPropertyActionListener value="#{node.id}" target="#{navigationBean.selectedNodeId}"/> #{node.label} </h:commandLink> </f:facet> </fx:navigation>
The JSF backing bean stores the selected node ID and will be updated through the commandLink.
public class NavigationBean { private long selectedNodeId; public long getSelectedNodeId() { return selectedNodeId; } public void setSelectedNodeId(long selectedNodeId) { this.selectedNodeId = selectedNodeId; } }
Includes external resources (CSS and JavaScripts) used by [fleXive] components. Place this in the
<head>
section of your HTML page.
<fx:includes [all="true|false"] [htmlEditor="true|false"] [jsonRpc="true|false"] [yui="true|false"]/>
If true, includes all resources supported by the tag. This leads to a performance penalty for loading and initializing the Javascript libraries, but is more convenient if performance is not critical.
If true, the HTML editor (currently TinyMCE) will be loaded and
initialized. Since TinyMCE must be initialized in the
<head>
section, unfortunately you have to set this attribute manually
when a
<fx:fxValueInput>
component is used for a HTML property.
The name of a TinyMCE configuration in
flexive.input.htmlEditorConfigs
.
Possible values:
default-basic
(the default setting),
default-full
.
Includes the JSON-RPC-Java library for Ajax calls via
JSON/RPC (the Javascript proxy can then be obtained with
flexive.yui.getJsonRpc()
).
Includes the Yahoo UI bootstrap library. If you want to use Yahoo UI components,
you also have to include a call to
<fx:yuiSetup/>
near the end of your page. You also have to specify the skin class on your page, the
most convenient way is through the body tag, e.g.:
<body class="yui-skin-sam">
.
Note that you can include the
<fx:includes>
tag more than once. This is useful if a component (e.g. the HTML editor)
is only needed on some pages and
<fx:includes>
is already included in the main page template.
Initializes the Yahoo UI widgets on the current page and loads all required libraries. Note that you still have to initialize the YUI bootstrap loader using <fx:includes yui="true">.
When using Yahoo UI you have to specify the skin class on your page, the most convenient way
is through the body tag, e.g.:
<body class="yui-skin-sam">
.
Renders a row container for a single input field
and renders a label for the input element. The input field(s) are stored in the tag body.
You can set a CSS-based tooltip using the tooltipKey attribute, or use labelKey and
append ".tooltip" to the base message key (e.g.
message.key
and
message.key.tooltip
).
<fx:formRow id="inputid" [label="label"] [labelKey="messagekey"] [newLine="true|false"] [width="widthInPx"] [height="heightInPx"]> [input element] </fx:formRow>
The client ID of the input element contained in the body.
The input element label.
The input label tooltip.
The input element label key (overrides label).
Message key of the tooltip (overrides tooltip, if not specified and labelKey is set,
it defaults to#{labelKey}.tooltip
)
Specifies whether a newline should be rendered after the input row (default: true).
Sets a fixed width on the row div (in pixels).
Sets a fixed height on the row div (in pixels).
Renders a HTML fieldset container for a group of formRow elements.
<fx:fieldSet [(legend="legend" | legendKey="legendKey")] [width="widthInPx"]> ... </fx:fieldSet>
The legend to be displayed in the fieldset header.
The message key of the localized message for the legend (overrides legend).
An optional attribute to specify a fixed width in pixels.
[fleXive] provides a set of JSF managed beans for working with [fleXive] in JSF applications. Some of them are usually used only in administration pages, some will probably be used in every [fleXive] application. For a complete reference consult the [fleXive] JavaDoc.
The fxContentViewBean provides a basic wrapper for the EJB content engine.
It is used to create and update instances, usually provided by the
<fx:content>
component.
To save a FxContent instance, you have to set the
content
property
of fxContentViewBean. Usually this is done with a JSF setPropertyActionListener,
take a look at
Example 7.2, “Edit an existing FxContent instance”.
You can also specify an optional success message that will be added
to the current JSF context after the content has been saved, using the
successMessage
property of fxContentViewBean.
When a content instance is created or saved, fxContentViewBean stores the primary key in the request, which can be used for URI rewriting as demonstrated in the section called “URI rewriting for contents”.
You can also add empty values to an existing content instance. This is especially useful for adding empty group elements for generic editors, as demonstrated in Example 7.5, “Add a new empty group to a content instance”.
The fxAuthenticationBean provides a simple wrapper for signing users on and off using [fleXive] security.
To create a login form, you have to
bind form inputs to the
username
and
password
properties
of fxAuthenticationBean,
add a JSF commandButton or commandLink that invokes the
fxAuthenticationBean.login
action, and
add a navigation case for the
loginSuccess
result.
If login fails,
login
is returned instead.
If desired, a checkbox mapped to the
takeover
property can be added to the login form.
It has to be checked, if other clients are logged in using the same credentials
(they will be logged out), otherwise logging in will fail, if the account does not
support
concurrent logins.
A logout link calls the
fxAuthenticationBean.logout
action method. The logout method returns
login
as a result.
Logging out always succeeds (except for internal errors), so no other navigation
case is necessary.
Be sure to perform a redirect on the navigation target since the HTTP session
is invalidated on logout (otherwise you may get
"Session already invalidated
"
errors). For example:
<navigation-case> <from-outcome>login</from-outcome> <to-view-id>/pub/login.xhtml</to-view-id> <redirect/> </navigation-case>
The fxMessageBean is an application-scoped bean that provides a localized message lookup service for JSF. Instead of a single resource bundle as provided by JSF's loadBundle, the fxMessageBean provides centralized access to the messages of all [fleXive] applications and plugins available in the current context.
The fxMessageBean implements the map interface and returns localized
messages for resource keys. For example,
#{fxMessageBean['Global.welcome']}
returns the message defined for the key
Global.welcome
for the current user's locale.
Message texts can include positional arguments that will be replaced
when the message is rendered. You can add a comma-separated
list of literal replacements or JSF-EL expressions to the resource key.
For example, the message
Global.welcome=Welcome, {0}
could be formatted using
#{fxMessageBean['Global.welcome,#{myBean.userName}']}
.
[fleXive] relies on fixed filenames for application and plugin messages. If you place a file with the given name in your application or plugin package, it will be automatically detected on startup by the fxMessageBean and will be available to all clients.
The [fleXive] resource bundle base names are:
For applications like the administration GUI, for example
ApplicationMessages.properties
or
ApplicationMessages_de.properties
.
For plugin packages, for example
PluginMessages.properties
or
PluginMessages_de.properties
.
[fleXive] includes a classpath resource resolver for Facelets that allows any Facelets resources (especially XHTML pages) to be included directly from JAR files in the classpath, instead of storing them in a web application archive (WAR).
The classpath resource resolver is declared in the [fleXive] components'
faces-config.xml
,
so no further steps are necessary for enabling it. The classpath resolver acts
as a fallback for the common Facelets resource resolver, i.e. if a resource
cannot be found using the default Facelets lookup, it attempts to load the same
path using the context class loader.
For example, if you store
/mywebdir/mypage.xhtml
in one of your JAR files, you can reference it just with this path in any of your
JSF config files, like the
faces-config.xml
.
It will then be delivered directly from your JAR file.