[jboss-user] [JBoss Seam] - Re: how to conditionally render a row of dataTable
ellenzhao
do-not-reply at jboss.com
Sun Aug 19 16:36:44 EDT 2007
I read that article. It seems there's a lot work to do in the infrastructure for adding a simple filtering feature....
Here are small view files in my own project demonstrating how I compose views. Hopefully they are readable enough....the foodCont is the name of a manager backing bean. This file is never directly accessed, but always included in other view files. All my directly-accessed views are started with a verb, shortly describing a use case.
Here the view-a-food.xhtml:
| <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
| "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
| <!-- version: $Id: view-a-food.xhtml 211 2007-08-16 16:42:02Z ningning $ -->
|
| <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:a="https://ajax4jsf.dev.java.net/ajax"
| template="layout/template.xhtml">
|
| <ui:define name="body">
|
| <h3>Food Item Detail</h3>
| <h:messages globalOnly="true" styleClass="message" />
|
| <ui:include src="/includes/food.xhtml" />
| <rich:spacer width="100%" height="7" />
|
| <div class="section"><s:button value="Ok"
| action="#{foodCont.quitAFoodView()}" /></div>
| </ui:define>
| </ui:composition>
|
Here the ultimately reusable food.xhtml:
| <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
| "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
| <!-- version: $Id: food.xhtml 210 2007-08-16 06:34:57Z ningning $ -->
|
| <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:a="https://ajax4jsf.dev.java.net/ajax">
|
| <div class="section">
| <!-- #################### begin error messages ##################### -->
| <s:fragment rendered="#{not empty foodCont.getErrors()}">
| <rich:dataList value="#{foodCont.getErrors()}" var="error">
| <h:outputText value="#{error.getMessage()}" class="error" />
| </rich:dataList>
| <rich:spacer width="100%" height="7" />
| </s:fragment>
| <!-- ####################### end error messages ############## -->
|
| <!-- ################# permission guard ######################### -->
| <s:fragment
| rendered="#{foodCont.getNeedsLogin() and not identity.loggedIn}">
| <div class="section"><h:form>
| <rich:panel>
| <f:facet name="header">Login</f:facet>
| <p>You need to login to perform this action</p>
| <div class="dialog"><h:panelGrid columns="2"
| rowClasses="prop" columnClasses="name,value">
| <h:outputLabel for="username">Username</h:outputLabel>
| <h:inputText id="username" value="#{foodCont.actor.name}" />
| <h:outputLabel for="password">Password</h:outputLabel>
| <h:inputSecret id="password"
| value="#{foodCont.actor.password}" />
| <h:outputLabel for="rememberMe">Remember me</h:outputLabel>
| <h:selectBooleanCheckbox id="rememberMe"
| value="#{identity.rememberMe}" />
| </h:panelGrid></div>
| </rich:panel>
| <div class="actionButtons"><h:commandButton value="Login"
| action="#{foodCont.login}" /></div>
| </h:form></div>
| <rich:spacer width="100%" height="7" />
| </s:fragment>
| <!-- ################## end of permission guard ############### -->
|
| <!-- ############### begin atomic fields of a food ################# -->
| <s:fragment>
| <s:decorate template="/layout/display.xhtml">
| <ui:define name="label">Food Description</ui:define>
| <h:outputText value="#{foodCont.food.longDesc}" />
| </s:decorate>
|
| <s:decorate template="/layout/display.xhtml">
| <ui:define name="label">Food Group: </ui:define>
| <h:outputText value="#{foodCont.food.fdGrp.desc_en}" />
| </s:decorate>
|
| <s:fragment rendered="#{foodCont.food.comName != null}">
| <s:decorate template="/layout/display.xhtml">
| <ui:define name="label">Common Name:</ui:define>
| <h:outputText value="#{foodCont.food.comName}" />
| </s:decorate>
| </s:fragment>
|
| <s:fragment rendered="#{foodCont.food.facName != null}">
| <s:decorate template="/layout/display.xhtml">
| <ui:define name="label">Manufacturer Name:</ui:define>
| <h:outputText value="#{foodCont.food.facName}" />
| </s:decorate>
| </s:fragment>
|
| <s:fragment rendered="#{foodCont.food.sciName != null}">
| <s:decorate template="/layout/display.xhtml">
| <ui:define name="label">Scientific Name:</ui:define>
| <h:outputText value="#{foodCont.food.sciName}" />
| </s:decorate>
| </s:fragment>
|
| <s:fragment rendered="#{foodCont.food.refuDesc != null}">
| <s:decorate template="/layout/display.xhtml">
| <ui:define name="label">Refuse Description:</ui:define>
| <h:outputText value="#{foodCont.food.refuDesc}" />
| </s:decorate>
|
| <s:decorate template="/layout/display.xhtml">
| <ui:define name="label">Refuse Percentage:</ui:define>
| <h:outputText value="#{foodCont.food.refuPercentage}%" />
| </s:decorate>
| </s:fragment>
|
| <s:fragment rendered="#{not empty foodCont.food.userOpinions}">
| <s:decorate template="/layout/display.xhtml">
| <ui:define name="label">Average User Rate:</ui:define>
| <h:outputText value="#{foodCont.food.getRateMean()}">
| <f:convertNumber type="number" maxFractionDigits="3" />
| </h:outputText>
| <h:outputText
| value=" from #{foodCont.food.getTotalRates()} rates" />
| </s:decorate>
| </s:fragment>
|
| <s:decorate template="/layout/display.xhtml">
| <ui:define name="label">Current Price per 100g:</ui:define>
| <h:outputText value="#{foodCont.food.pricePer100g}">
| <f:convertNumber pattern="? ###0.00" />
| </h:outputText>
| </s:decorate>
|
| <rich:spacer width="100%" height="7" />
| </s:fragment>
| <!-- ############### end of atomic fields of a food ############### -->
|
| <!-- ################# begin weight convertor #################### -->
| <s:fragment rendered="#{not empty foodCont.food.getWeights()}">
| <div class="section"><h:form>
|
| <s:decorate template="/layout/edit.xhtml">
| <ui:define name="label">Amount: </ui:define>
| <h:inputText value="#{foodCont.food.givenAmount}"
| required="true" />
| </s:decorate>
|
| <h:selectOneMenu id="selectUnit" class="value"
| value="#{foodCont.food.givenWeight}">
| <s:selectItems value="#{foodCont.food.weights}" var="unit"
| label="#{unit.msreDesc}"
| noSelectionLabel="Select a weight unit..." />
| <s:convertEntity />
| </h:selectOneMenu>  
|
| <h:commandButton type="submit" value="Convert to gram"
| action="#{foodCont.food.convertWeight()}" />
| </h:form>    <h:outputText
| value="#{foodCont.food.getWeightInGram()}">
| <f:convertNumber type="number" maxFractionDigits="3" />
| </h:outputText> gram</div>
| <rich:spacer width="100%" height="7" />
| </s:fragment>
| <!-- ################# end weight convertor #################### -->
|
| <!-- ############### begin control options ################# -->
| <div class="section"><rich:toolBar height="26"
| itemSeparator="disc">
| <rich:toolBarGroup
| rendered="#{(identity.hasRole('admin') and (foodCont.getUseCases().peek() ne 'updateAFood')) or (not identity.loggedIn)}">
| <s:link action="#{foodCont.tryUpdateAFood()}" value="Update Price" />
| </rich:toolBarGroup>
|
| <rich:toolBarGroup>
| <s:link
| action="#{userOpinionCont.startAddOpinion(foodCont.food)}"
| value="Rate and/or Comment it"
| rendered="#{userOpinionCont.getUseCases().peek() ne 'addOrUpdateUserOpinion'}" />
| </rich:toolBarGroup>
|
| <rich:toolBarGroup>
| <s:link action="#{foodCont.food.setRenderNutrients(true)}"
| value="Show Nutrient Facts"
| rendered="#{not foodCont.food.getRenderNutrients()}" />
| <s:link action="#{foodCont.food.setRenderNutrients(false)}"
| value="Fold Nutrient Facts"
| rendered="#{foodCont.food.getRenderNutrients()}" />
| <s:link action="#{foodCont.food.setRenderComments(true)}"
| value="Show User Comments"
| rendered="#{foodCont.food.getComments().size > 0 and not foodCont.food.getRenderComments()}" />
| <s:link action="#{foodCont.food.setRenderComments(false)}"
| value="Fold User Comments"
| rendered="#{foodCont.food.getComments().size > 0 and foodCont.food.getRenderComments()}" />
| <s:link action="#{foodCont.food.setRenderRecipes(true)}"
| value="Show Containing Recipes"
| rendered="#{foodCont.food.getIngredients().size > 0 and not foodCont.food.getRenderRecipes()}" />
| <s:link action="#{foodCont.food.setRenderRecipes(false)}"
| value="Fold Containing Recipes"
| rendered="#{foodCont.food.getIngredients().size > 0 and foodCont.food.getRenderRecipes()}" />
| </rich:toolBarGroup>
| </rich:toolBar>
| <rich:spacer width="100%" height="7" />
| </div>
| <!-- ################ end of control options ################## -->
|
| <!-- ############### begin of price update form ################## -->
| <s:fragment
| rendered="#{foodCont.getUseCases().peek() eq 'updateAFood'}">
| <div class="section"><h:form>
| <s:decorate template="/layout/edit.xhtml">
| <ui:define name="label">Current Price per 100g:</ui:define>
| <h:inputText value="#{foodCont.food.pricePer100g}"
| required="true" />
| <h:outputText value=" euro" />
| </s:decorate>
| <div class="section"><h:commandButton value="update"
| action="#{foodCont.doneUpdateAFood()}" /><s:button
| value="Cancel" action="#{foodCont.cancelUpdatePrice()}" /></div>
| </h:form></div>
| <div class="section"><rich:spacer width="100%" height="7" /></div>
| </s:fragment>
| <!-- ############### end of price update form ################## -->
|
| <!-- ############### begin of user opinion form ############### -->
| <s:fragment
| rendered="#{userOpinionCont.getUseCases().peek() eq 'addOrUpdateUserOpinion'}">
| <div class="section"><ui:include src="user-opinion.xhtml" />
| <rich:spacer width="100%" height="7" /></div>
| </s:fragment>
| <!-- ################ end of user opinion form ################## -->
|
| <!-- ############## begin of nutrient facts ################### -->
| <s:fragment
| id="nutrients" rendered="#{foodCont.food.getRenderNutrients()}">
| <div class="section">
| <h4>Nutrient Facts</h4>
| <h:form>
| <rich:dataTable id="nutrientFacts" rows="25"
| value="#{foodCont.food.getNutrients()}" var="n">
| <rich:column>
| <f:facet name="header">
| <h:outputText value="Nutrient Desc" />
| </f:facet>
| <h:outputText value="#{n.nutr.nutrDesc}" />
| </rich:column>
|
| <rich:column>
| <f:facet name="header">
| <h:outputText value="Amount per 100g" />
| </f:facet>
| <h:outputText value="#{n.nutrVal} #{n.nutr.units}">
| <f:convertNumber type="number" maxFractionDigits="3" />
| </h:outputText>
| </rich:column>
|
| <rich:column rendered="#{foodCont.food.getWeightInGram()>0}">
| <f:facet name="header">
| <h:outputText
| value="Amount in #{foodCont.food.getGivenAmount()} #{foodCont.food.getGivenWeight().msreDesc}" />
| </f:facet>
| <h:outputText
| value="#{foodCont.food.getWeightInGram() / 100 * n.nutrVal}">
| <f:convertNumber type="number" maxFractionDigits="3" />
| </h:outputText>
| #{n.nutr.units}
| </rich:column>
| </rich:dataTable>
| <rich:datascroller for="nutrientFacts" />
| </h:form></div>
| <rich:spacer width="100%" height="7" />
| </s:fragment>
| <!-- ################# end of nutrient facts #################### -->
|
| <!-- ################# begin of user comments table ############# -->
| <s:fragment id="userCommments"
| rendered="#{foodCont.food.getComments().size > 0 and foodCont.food.getRenderComments()}">
| <div class="section"><h:form>
| <rich:dataTable id="commentsTable" rows="25"
| value="#{foodCont.food.getComments()}" var="o">
| <rich:column>
| <f:facet name="header">
| <h:outputText value="User" />
| </f:facet>
| <h:outputText value="#{o.user.name}" />
| </rich:column>
|
| <rich:column>
| <f:facet name="header">
| <h:outputText value="Rate" />
| </f:facet>
| <h:outputText value="#{o.rate}" />
| </rich:column>
|
| <rich:column>
| <f:facet name="header">
| <h:outputText value="Comment" />
| </f:facet>
| <h:outputText value="#{o.comment}" />
| </rich:column>
|
| <rich:column>
| <f:facet name="header">
| <h:outputText value="Date" />
| </f:facet>
| <h:outputText value="#{o.version}" />
| </rich:column>
| </rich:dataTable>
| <rich:datascroller for="commentsTable" />
| </h:form></div>
| <rich:spacer width="100%" height="7" />
| </s:fragment>
| <!-- ################# end of user comments table ############# -->
|
| <!-- ################# begin of containing recipes table ########### -->
| <s:fragment
| rendered="#{foodCont.food.getIngredients().size > 0 and foodCont.food.getRenderRecipes()}">
| <div class="section"><h:form>
| <rich:dataTable id="recipesTable" rows="25"
| value="#{foodCont.food.getIngredients()}" var="i">
| <rich:column>
| <f:facet name="header">
| <h:outputText value="Recipe Id" />
| </f:facet>
| <h:outputText value="#{i.recipe.id}" />
| </rich:column>
|
| <rich:column>
| <f:facet name="header">
| <h:outputText value="Recipe Name" />
| </f:facet>
| <h:outputText value="#{i.recipe.name}" />
| </rich:column>
|
| <rich:column>
| <f:facet name="header">
| <h:outputText value="Weight Percentage" />
| </f:facet>
| <h:outputText value="#{i.getWeightPercentage()}">
| <f:convertNumber pattern="###0.00%" />
| </h:outputText>
| </rich:column>
|
| <rich:column>
| <f:facet name="header">
| <h:outputText value="Option" />
| </f:facet>
| <h:commandButton
| action="#{foodCont.selectContainingRecipe(i)}"
| value="view the recipe" />
| </rich:column>
| </rich:dataTable>
| <rich:datascroller for="recipesTable" />
| </h:form></div>
| <rich:spacer width="100%" height="7" />
| </s:fragment>
| <!-- ################# end of containing recipes table ########### --></div>
| </ui:composition>
|
yes my entity object is very rich of behaviours and transient member fields...
Here a bit navigation rules....
| <page view-id="/view-a-food.xhtml">
| <navigation from-action="#{foodCont.quitAFoodView()}">
| <rule
| if="#{foodCont.getUseCases().peek() eq 'readFoods'}">
| <redirect view-id="/view-foods.xhtml" />
| </rule>
| </navigation>
| <navigation from-action="#{recipeManager.setRecipe(r)}">
| <redirect view-id="/view-a-recipe.xhtml" />
| </navigation>
| <navigation>....</navigation>
| </page>
|
the code in the conversation beans is very lean, just does stuffs like begin/end conversations, push/pop/remove use cases, etc.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4075594#4075594
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4075594
More information about the jboss-user
mailing list