-
1. Re: Component configuration with complex types
atao Jul 27, 2007 3:35 PM (in response to jbuechel)Hello,
I just started to work on a menu build through configuration file, but:
- without using any of the "standard" configuration files as "components.xml": I define a specific "menus.xml" file in the same way that pages.xml
- and agnostic about implementation, even if by default it'll be RichFaces.
Atm a lot of things are still missing but it works. If you are interested... -
2. Re: Component configuration with complex types
jbuechel Jul 30, 2007 1:45 AM (in response to jbuechel)Hi
Yes i am. If you could provide some sample code would be great! -
3. Re: Component configuration with complex types
jbuechel Jul 31, 2007 12:41 PM (in response to jbuechel)I'm wondering how others are configuring their menus..
Or is there a completely different approach? Just a hint? ;-) -
4. Re: Component configuration with complex types
pmuir Jul 31, 2007 5:38 PM (in response to jbuechel)You could do this via components.xml but it would be quite verbose due to not being able to nest components. If this is a static menu, then I would ui:include a facelet.
-
5. Re: Component configuration with complex types
atao Jul 31, 2007 5:40 PM (in response to jbuechel)It's really a work in progress.
I just checked it againt Seam 2 cvs.
So, the code as it is...
All the calls go through MenuManagerpackage org.jboss.seam.menu; import static org.jboss.seam.ScopeType.APPLICATION; import static org.jboss.seam.annotations.Install.BUILT_IN; import java.io.InputStream; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.dom4j.DocumentException; import org.dom4j.Element; import org.jboss.seam.Component; import org.jboss.seam.annotations.Create; import org.jboss.seam.annotations.Install; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.intercept.BypassInterceptors; import org.jboss.seam.contexts.Contexts; import org.jboss.seam.log.LogProvider; import org.jboss.seam.log.Logging; import org.jboss.seam.menu.MenuItem.ItemType; import org.jboss.seam.menu.NavigationFactory.NavigationType; import org.jboss.seam.util.Resources; import org.jboss.seam.util.XML; /** * Provide menu items * * - in the same application, it should be possible to use different implementations through component configuration * atm the only one available is RichFaces * - in menus.xml, everything is a item, without no information about how to show these items * - the way that a menu is inserted in a page is fixed on from the page side with the choice between 3 methods: * - getNavigationItem : return an simple item * - getNavigationMenu : return a single top menu * - getNavigationMenus: retourne a list of top menus * What is exactly returned depends of the implementation. * - any item, whatever its declaration place is, can be named with "id" attribute and so reused * (in a tag, through attribut "refid") * - TODO to set parameters specifics for a given implementation, with the tag * <specific type="richfaces">...</specific> * inside any item. * - all seam parameters defined for a link are directly available; atm only propagation * - the children of an item can be "unwrapped" i.e. used in place of the item. * * Syntaxe of a menu file: * <menus> * <item id="..."> * <item id="..." * label="..." * icon="..." * description * rendered * disabled * action * type * propagation * split * target * > * ... * </item> * <item> * ... * </item> * ... * </menus> * * @author Pierre * */ @Scope(APPLICATION) @BypassInterceptors @Name("menumanager") @Install(precedence = BUILT_IN) public class MenuManager { private static String EMPTY_STRING = ""; private static String TRUE_STRING = "true"; private static String ITEM_TAG = "item"; private static String ID_ATTR = "id"; private static String REFID_ATTR = "refid"; private static String ICON_ATTR = "icon"; private static String LABEL_ATTR = "label"; private static String HOTKEY_ATTR = "accesskey"; private static String DESCRIPTION_ATTR = "description"; private static String RENDERED_ATTR = "rendered"; private static String DISABLED_ATTR = "disabled"; private static String ACTION_ATTR = "action"; private static String TYPE_ATTR = "type"; private static String PROPAGATION_ATTR = "propagation"; private static String TARGET_ATTR = "target"; private static String UNWRAP_ATTR = "unwrap"; public static NavigationType MENU_LIST_TYPE = NavigationType.GROUP; public static NavigationType MENU_TYPE = NavigationType.ROOT; private String menusFile = "/WEB-INF/menus.xml"; private String menuImpl = "Richfaces"; private static final LogProvider log = Logging .getLogProvider(MenuManager.class); private Map<String, MenuItem> menusById = Collections .synchronizedMap(new HashMap<String, MenuItem>()); private NavigationFactory factory; @Create public void initialize() { InputStream stream = Resources.getResourceAsStream(menusFile, null); if (stream == null) { log.debug("no " + menusFile + " file found"); } if (stream != null) { log.debug("reading " + menusFile); parse(stream); } factory = NavigationFactory.getInstance(menuImpl); } public static MenuManager instance() { if (Contexts.isApplicationContextActive()) { return (MenuManager) Component.getInstance(MenuManager.class, APPLICATION); } else // tests { return new MenuManager(); } } /** *Get a MenuItem from cache */ public MenuItem getMenu(String id) { MenuItem item = menusById.get(id); if (null == item) return null; if ((item.getRefid() != null) && !EMPTY_STRING.equals(item.getRefid())) { item = menusById.get(item.getRefid()); } return item; } /** * Get a Menu List to insert in a menu bar */ public Object getNavigationMenus(String id) { return factory .getNavigationItem(menusById, getMenu(id), MENU_LIST_TYPE); } /** * Get a Menu to insert in a menu bar */ public Object getNavigationMenu(String id) { return factory.getNavigationItem(menusById, getMenu(id), MENU_TYPE); } /** * Get a menu item */ public Object getNavigationItem(String id) { return factory.getNavigationItem(menusById, getMenu(id)); } /** * Parse a menus.xml file */ private void parse(InputStream stream) { Element root = getDocumentRoot(stream); List<Element> elements = root.elements(ITEM_TAG); for (Element item : elements) { String itemId = item.attributeValue(ID_ATTR); if (null == itemId || EMPTY_STRING.equals(itemId)) { // TODO: use an other type of exception? throw new IllegalStateException("Must specify item-id for '" + item.attributeValue(LABEL_ATTR) + "' tag."); } parseItem(item); } } private String parseLabel(Element element) { return element.attributeValue(LABEL_ATTR); } private ItemType parseItemType(Element element) { String type = element.attributeValue(TYPE_ATTR); if (null == type) return ItemType.DEFAULT; try { return ItemType .valueOf(type.toUpperCase()); } catch (IllegalArgumentException e) { return ItemType.DEFAULT; } } private MenuItem parseItem(Element element) { String itemId = element.attributeValue(ID_ATTR); MenuItem item = null; String refid = element.attributeValue(REFID_ATTR); if (null != refid && !EMPTY_STRING.equals(refid)) { item = new MenuItem(refid); item.setUnwrap(Boolean.parseBoolean(element .attributeValue(UNWRAP_ATTR))); } else { item = new MenuItem(itemId, element.attributeValue(ICON_ATTR), parseLabel(element), element.attributeValue(HOTKEY_ATTR), element.attributeValue(DESCRIPTION_ATTR), Boolean .parseBoolean(element.attributeValue(RENDERED_ATTR, TRUE_STRING)), Boolean.parseBoolean(element .attributeValue(DISABLED_ATTR)), element .attributeValue(ACTION_ATTR), parseItemType(element), element .attributeValue(PROPAGATION_ATTR), element .attributeValue(TARGET_ATTR)); item.setText(element.getText()); for (Element child : (List<Element>) element.elements(ITEM_TAG)) { item.getItems().add(parseItem(child)); } } if (null != itemId && !EMPTY_STRING.equals(itemId)) { menusById.put(itemId, item); } return item; } /** * Get the root element of the document */ private static Element getDocumentRoot(InputStream stream) { try { return XML.getRootElement(stream); } catch (DocumentException de) { throw new RuntimeException(de); } } /** * @return the menuImpl */ public String getMenuImpl() { return this.menuImpl; } /** * @param menuImpl the menuImpl to set */ public void setMenuImpl(String menuImpl) { this.menuImpl = menuImpl; } /** * @return the menusFile */ public String getMenusFile() { return this.menusFile; } /** * @param menusFile the menusFile to set */ public void setMenusFile(String menusFile) { this.menusFile = menusFile; } public Map<String, MenuItem> getMenus() { return menusById; } }
with tree classes to do the job
- an abstract one: NavigationFactory
- Richfaces implementation: RichFacesNavigationFactory
- and a value object: MenuItempackage org.jboss.seam.menu; import java.util.Map; import org.jboss.seam.core.Expressions; import org.jboss.seam.log.LogProvider; import org.jboss.seam.log.Logging; public abstract class NavigationFactory { public static enum NavigationType { ROOT, GROUP, INSIDE } protected static final String EMPTY_STRING = ""; private static final String PATH_SEP = "."; protected Map<String, MenuItem> refmap; private static final String CLASS_SUFFIX = NavigationFactory.class .getSimpleName(); protected static final LogProvider log = Logging .getLogProvider(NavigationFactory.class); protected NavigationFactory() { } /** * * @param impl either a simple prefix if the implementation is in the same package * or a full package name for a NavigationFactory class in an other package * @return */ public static NavigationFactory getInstance(String impl) { NavigationFactory factory = null; String className = impl; try { if (impl.indexOf(PATH_SEP) < 0) { className = NavigationFactory.class.getPackage().getName() + PATH_SEP + className; if (!impl.endsWith(CLASS_SUFFIX)) { className += CLASS_SUFFIX; } } Class clazz = Class.forName(className); factory = (NavigationFactory) clazz.newInstance(); } catch (ClassNotFoundException e) { log.error("Navigation factory not found for '" + className + "'.", e); } catch (IllegalAccessException e) { log.error("Navigation factory not accessible for '" + className + "'.", e); } catch (InstantiationException e) { log.error("Navigation factory can't be instantiated for '" + className + "'.", e); } return factory; } /** * gives a standard navigation item * * @param itemId * @return */ public Object getNavigationItem(Map<String, MenuItem> refmap, MenuItem item) { return getNavigationItem(refmap, item, NavigationType.INSIDE); } /** * gives a navigation item, either a standard one with NavigationType.INSIDE or a menu bar's one * with NavigationType.ROOT or NavigationType.GROUP * * @param itemId * @param type * @return */ public Object getNavigationItem(Map<String, MenuItem> refmap, MenuItem item, NavigationType type) { this.refmap = refmap; return getNavigationItem(item, type); } protected abstract Object getNavigationItem(MenuItem item, NavigationType type); protected MenuItem getRefItem(MenuItem item) { if ((null == item) || (null == item.getRefid()) || EMPTY_STRING.equals(item.getRefid())) { return item; } return getRefItem(refmap.get(item.getRefid())); } protected Object parseLabel(String expression) { return null == expression ? null : Expressions.instance() .createValueExpression(expression).getValue(); } protected Object parseAction(String expression) { return null == expression ? null : Expressions.instance() .createValueExpression(expression).getValue(); } }
package org.jboss.seam.menu; import javax.el.ELContext; import javax.el.ExpressionFactory; import javax.el.MethodExpression; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import org.jboss.seam.el.SeamExpressionFactory; import org.jboss.seam.ui.component.html.HtmlLink; import org.richfaces.component.html.HtmlDropDownMenu; import org.richfaces.component.html.HtmlMenuGroup; import org.richfaces.component.html.HtmlMenuItem; import org.richfaces.component.html.HtmlMenuSeparator; import org.richfaces.component.html.HtmlToolBarGroup; public class RichfacesNavigationFactory extends NavigationFactory { protected UIComponent getNavigationItem(MenuItem item, NavigationType type) { item = getRefItem(item); if (null == item) { item = new MenuItem(null); } if (NavigationType.ROOT == type) { return getDropDownMenu(item); } else if (NavigationType.GROUP == type) { return getToolBarGroup(item); } else if (item.getItems().isEmpty()) { if ((null == item.getLabel()) || EMPTY_STRING.equals(item.getLabel())) { return getMenuSeparator(item); } else { return getMenuItem(item); } } else { return getMenuGroup(item); } } private HtmlToolBarGroup getToolBarGroup(MenuItem item) { HtmlToolBarGroup group = new HtmlToolBarGroup(); group.setId(item.getId()); group.setRendered(item.isRendered()); copyChildren(item, group, NavigationType.ROOT); return group; } private HtmlDropDownMenu getDropDownMenu(MenuItem item) { HtmlDropDownMenu menu = new HtmlDropDownMenu(); menu.setId(item.getId()); menu.setValue(parseLabel(item.getLabel())); menu.setRendered(item.isRendered()); copyChildren(item, menu, NavigationType.INSIDE); return menu; } private HtmlMenuItem getMenuItem(MenuItem item) { HtmlMenuItem navItem = new HtmlMenuItem(); navItem.setId(item.getId()); navItem.setIcon(item.getIcon()); navItem.setRendered(item.isRendered()); boolean linked = false; if (null == item.getPropagation()) { if (MenuItem.ItemType.DIRECT.equals(item.getType())) // i.e. a link with its protocole, e.g. "http://..." { navItem.setOnclick("document.location.href='" + parseAction(item.getAction()) + "'"); navItem.setSubmitMode("none"); linked = true; } else if (MenuItem.ItemType.BINDING.equals(item.getType())) { ExpressionFactory factory = SeamExpressionFactory.INSTANCE; ELContext context = FacesContext.getCurrentInstance() .getELContext(); MethodExpression expression = factory.createMethodExpression( context, item.getAction(), Object.class, new Class<?>[0]); navItem.setActionExpression(expression); linked = true; } if (linked) { navItem.setDisabled(item.isDisabled()); navItem.setValue(parseLabel(item.getLabel())); } } if (!linked) // by default, jsf view id; used also if propagation is specified { HtmlLink link = new HtmlLink(); link.setValue(parseLabel(item.getLabel())); link.setView((String) parseAction(item.getAction())); link.setPropagation(item.getPropagation()); link.setDisabled(item.isDisabled()); navItem.getChildren().add(link); navItem.setSubmitMode("none"); navItem.setStyleClass("withlink"); } return navItem; } private HtmlMenuGroup getMenuGroup(MenuItem item) { HtmlMenuGroup group = new HtmlMenuGroup(); group.setId(item.getId()); group.setIcon(item.getIcon()); group.setValue(parseLabel(item.getLabel())); group.setDisabled(item.isDisabled()); group.setRendered(item.isRendered()); copyChildren(item, group, NavigationType.INSIDE); return group; } private HtmlMenuSeparator getMenuSeparator(MenuItem item) { return new HtmlMenuSeparator(); } private void copyChildren(MenuItem item, UIComponent group, NavigationType type) { for (MenuItem child : item.getItems()) { if (null != child && child.isUnwrap()) { child = getRefItem(child); for (MenuItem subchild : child.getItems()) { group.getChildren().add(getNavigationItem(subchild, type)); } } else { group.getChildren().add(getNavigationItem(child, type)); } } } }
package org.jboss.seam.menu; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Nota: attribute "type" gives the type of action, with value "direct", "binding" or "default" * The default value is associated with jsf link. * * Nota: to deal with implementation specific needs, use "specific" tag in the body of the item. * The implementation is specified by the attribute "type" of this tag. This specific data are stored * in data property. * * @author Pierre * */ public class MenuItem { public static enum ItemType { DIRECT, BINDING, DEFAULT } private String id; private String refid; private boolean unwrap; private String text; private String icon; private String label; private String hotkey; private String description; private boolean rendered; private boolean disabled; private String action; private ItemType type; private String propagation; private String target; private Map<String, Object> data; private List<MenuItem> items = new ArrayList<MenuItem>(); public MenuItem(String refid) { this.refid = refid; } public MenuItem(String id, String icon, String label, String hotkey, String description, boolean rendered, boolean disabled, String action, ItemType type, String propagation, String target) { this.id = id; this.icon = icon; this.label = label; this.description = description; this.rendered = rendered; this.disabled = disabled; this.action = action; this.type = type; this.propagation = propagation; this.hotkey = hotkey; this.target = target; } /** * @return the items */ public List<MenuItem> getItems() { return this.items; } /** * @param items the items to set */ public void setItems(List<MenuItem> items) { this.items = items; } /** * @return the action */ public String getAction() { return this.action; } /** * @param action the action to set */ public void setAction(String action) { this.action = action; } /** * @return the action type */ public ItemType getType() { return this.type; } /** * @param type the type to set */ public void setType(ItemType type) { this.type = type; } /** * @return the propagation */ public String getPropagation() { return this.propagation; } /** * @param propagation the propagation to set */ public void setPropagation(String propagation) { this.propagation = propagation; } /** * @return the description */ public String getDescription() { return this.description; } /** * @param description the description to set */ public void setDescription(String description) { this.description = description; } /** * @return the disabled */ public boolean isDisabled() { return this.disabled; } /** * @param disabled the disabled to set */ public void setDisabled(boolean disabled) { this.disabled = disabled; } /** * @return the icon */ public String getIcon() { return this.icon; } /** * @param icon the icon to set */ public void setIcon(String icon) { this.icon = icon; } /** * @return the id */ public String getId() { return this.id; } /** * @param id the id to set */ public void setId(String id) { this.id = id; } /** * @return the label */ public String getLabel() { return this.label; } /** * @param label the label to set */ public void setLabel(String label) { this.label = label; } /** * @return the rendered */ public boolean isRendered() { return this.rendered; } /** * @param rendered the rendered to set */ public void setRendered(boolean rendered) { this.rendered = rendered; } /** * @return the target */ public String getTarget() { return this.target; } /** * @param target the target to set */ public void setTarget(String target) { this.target = target; } /** * @return the hotkey */ public String getHotkey() { return this.hotkey; } /** * @param hotkey the hotkey to set */ public void setHotkey(String hotkey) { this.hotkey = hotkey; } /** * @return the data */ public Map<String, Object> getData() { return this.data; } /** * @param data the data to set */ public void setData(Map<String, Object> data) { this.data = data; } public void addData(String impl, Object data) { if (null == this.data) { this.data = new HashMap<String, Object>(); } this.data.put(impl, data); } /** * @return the refid */ public String getRefid() { return this.refid; } /** * @param refid the refid to set */ public void setRefid(String refid) { this.refid = refid; } /** * The text from the item body * * @return the text */ public String getText() { return this.text; } /** * @param text the text to set */ public void setText(String text) { this.text = text; } /** * @return the unwrap */ public boolean isUnwrap() { return this.unwrap; } /** * @param unwrap the unwrap to set */ public void setUnwrap(boolean unwrap) { this.unwrap = unwrap; } public String toString() { return this.getClass().getSimpleName() + ", id = " + id + (refid == null ? ", " : " (" + refid + "), ") + "label = '" + label + "', action = " + action; } }
Then to use it:
- create a menus.xml, e.g.:<menus> <item id="HomeMenu" > <item refid="EntityMenu" /> <item refid="MainMenu" unwrap="true" /> </item> <item id="EntityMenu" label="#{messages['view.menu.label.entities']}" > <item label="#{messages['view.menu.list.person']}" action="/PersonList.xhtml" propagation="none" /> <item label="#{messages['view.menu.list.branch']}" action="/BranchList.xhtml" propagation="none" /> <item label="#{messages['view.menu.list.fund']}" action="/FundList.xhtml" propagation="none" /> <item label="#{messages['view.menu.list.payslip']}" action="/PayslipList.xhtml" propagation="none" /> <item label="#{messages['view.menu.list.worker']}" action="/WorkerList.xhtml" propagation="none" /> <item label="#{messages['view.menu.list.contract']}" action="/ContractList.xhtml" propagation="none" /> <item label="#{messages['view.menu.list.address']}" action="/AddressList.xhtml" propagation="none" /> <item label="#{messages['view.menu.list.rubric']}" action="/RubricList.xhtml" propagation="none" /> <item label="#{messages['view.menu.list.profil']}" action="/ProfilList.xhtml" propagation="none" /> <item label="#{messages['view.menu.list.job']}" action="/JobList.xhtml" propagation="none" /> <item label="#{messages['view.menu.list.payItem']}" action="/PayItemList.xhtml" propagation="none" /> </item> <item id="MainMenu" > <item refid="FileMenu" /> <item refid="EmployeeMenu" /> <item refid="PayslipMenu" /> <item refid="ReportMenu" /> <item refid="ToolMenu" /> <item refid="HelpMenu" /> </item> <item id="FileMenu" label="#{messages['menu.company']}"> <item label="#{messages['menu.quit']}" action="#{messages['view.menu.link.site.company']}" type="direct" /> </item> <item id="EmployeeMenu" label="#{messages['menu.employee']}"> <item label="#{messages['menu.employee.list']}" action="/WorkerList.xhtml" propagation="none" /> <item /> <item label="#{messages['menu.employee.contract.list']}" action="/ContractList.xhtml" propagation="none" /> </item> <item id="PayslipMenu" label="#{messages['menu.payslip']}"> <item label="#{messages['menu.payslip.list']}" action="/PayslipList.xhtml" propagation="none" /> </item> <item id="ReportMenu" label="#{messages['menu.report']}"> </item> <item id="ToolMenu" label="#{messages['menu.tool']}"> </item> <item id="HelpMenu" label="#{messages['menu.help']}"> <item label="#{messages['view.menu.label.site.jboss']}" action="#{messages['view.menu.link.site.jboss']}" type="direct" /> <item label="#{messages['view.menu.label.help']}" action="/Help.xhtml" target="_blank"/> </item> <item id="PersonListMenu" > <item label="#{messages['entity.person.name']}"> <item label="#{messages['view.global.button.add']}" action="/PersonEdit.xhtml" /> </item> </item> <item id="ContractListMenu" > <item label="#{messages['entity.contract.name']}"> <item label="#{messages['view.global.button.add']}" action="/WorkerList.xhtml" /> </item> </item> <item id="ContractViewMenu" > <item label="#{messages['entity.contract.name']}"> <item label="#{messages['menu.link.contract.create.payslips']}" action="#{customContractHome.createPayslip}" type="binding"/> </item> </item> </menus>
- and use it with a menu layout:<rich:toolBar xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:rich="http://richfaces.ajax4jsf.org/rich"> <h:form id="menuBar"> <style type="text/css"> .withlink a {display:inline-block; width: 100%;} html>/**/body .withlink a {display: block; width: 100%;} html>/**/body .withlink span{float: left;} html>/**/body .withlink span + span {float: none; display: block;} </style> <style type="text/css"> .withHighIndex div {z-index: 100;} </style> <rich:toolBarGroup> <h:outputFormat value="#{messages['view.menu.title.project']}"> <f:param value="#{projectName}" /> </h:outputFormat> </rich:toolBarGroup> <ui:insert name="menu" /> <f:subview rendered="#{empty menuref}"> <rich:toolBarGroup> <s:link view="/home.xhtml" value="#{messages['view.menu.link.home']}"/> </rich:toolBarGroup> <rich:toolBarGroup styleClass="withHighIndex"> <rich:dropDownMenu value="#{messages['view.menu.label.entities']}"> <rich:menuItem styleClass="withlink" submitMode="none"> <s:link value="#{messages['view.menu.list.profil']}" view="/ProfilList.xhtml" propagation="none" /> </rich:menuItem> [...] <rich:menuItem styleClass="withlink" submitMode="none"> <s:link value="#{messages['view.menu.list.person']}" view="/PersonList.xhtml" propagation="none" /> </rich:menuItem> </rich:dropDownMenu> <rich:dropDownMenu value="#{messages['view.menu.help']}"> <rich:menuItem value="#{messages['view.menu.label.site.jboss']}" onclick="document.location.href='#{messages['view.menu.link.site.jboss']}'" submitMode="none" /> </rich:dropDownMenu> </rich:toolBarGroup> </f:subview> <rich:toolBarGroup location="right"> <h:outputFormat value="#{messages['org.jboss.seam.loginSuccessful']}" rendered="#{identity.loggedIn}"> <f:param value="#{identity.username}"/> </h:outputFormat> <s:link view="/login.xhtml" value="#{messages['view.login.button.login']}" rendered="#{not identity.loggedIn}"/> <s:link view="/home.xhtml" action="#{identity.logout}" value="#{messages['view.login.button.logout']}" rendered="#{identity.loggedIn}"/> </rich:toolBarGroup> </h:form> </rich:toolBar>
and some view:<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:rich="http://richfaces.ajax4jsf.org/rich" xmlns:j="http://ext.joda.org/jsf/components" template="layout/template.xhtml"> <ui:param name="menuref" value="#{menumanager.getMenu('FundViewMenu')}" /> <ui:define name="menu"> <rich:toolBarGroup styleClass="withHighIndex" binding="#{menumanager.getNavigationMenus('FundViewMenu')}" /> </ui:define> <ui:define name="body"> <h:messages globalOnly="true" styleClass="message" id="globalMessages"/> <rich:panel> <f:facet name="header"> <h:outputFormat value="#{messages['view.edit.title.show.entity']}"> <f:param value="#{messages['entity.fund.name']}"/> </h:outputFormat> </f:facet> <s:decorate id="id" template="layout/display.xhtml"> <ui:define name="label"> <h:outputText value="#{messages['entity.fund.id.label']}"/> </ui:define> #{fundHome.instance.id} </s:decorate> [...] </ui:define> </ui:composition>
-
6. Re: Component configuration with complex types
jbuechel Aug 2, 2007 2:32 AM (in response to jbuechel)Wow! Thanks a lot for your effort. I'll give it a try.
jonas