在进行了我的一位同事的项目后,我面临着一些小问题的对话。我被要求复制一个组件并给它一个新名称。但是开始出现了问题:我能够构建对话并将组件发送到我的支持bean(不幸的是一个SessionScoped),同时新名称找到了它并且保存工作也是如此但是我的对话的保存按钮显示有些奇怪行为。并且代码将显示我已经尝试了很多变体(具有不同的结果,在上面的注释中描述)。
最后,我只想要三件小事:让JSF生命周期只调用一次,我的inputText字段需要工作,成功保存后仍然可用的视图。
如果您需要更多代码,例如以bal或者支持bean开头的复合组件,只需删除一个注释,我就会处理它。
我意识到每次从数据库中获取数据都是ui:repeat的糟糕方式,但我还没有看到与SessionScoped-Bean不同的方式我必须使用(ViewScoped肯定会在这里变得更好,但改变它的时间,就像往常一样,不存在)。
这是我的代码,使用Primefaces 5.3和当前版本的Bootsfaces:
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:b="http://bootsfaces.net/ui"
xmlns:bal="http://java.sun.com/jsf/composite/bal/components">
<ui:composition template="/template/main.xhtml">
<ui:define name="content">
<bal:pageHeading title="#{msg.menu_settings} » #{msg.menu_components}">
<h:form>
<div class="btn-group pull-right">
<b:commandButton look="link" styleClass="as-link" size="lg" action="#{componentController.createCategory()}" value="#{msg.create_category}" title="#{msg.create_category}" iconAwesome="plus-circle" />
</div>
</h:form>
</bal:pageHeading>
<bal:row id="panelRow">
<h:form id="masterForm">
<ui:repeat value="#{componentController.getComponentcategoryListByCompany(loginController.company)}" var="componentcategory">
<bal:panel title="#{componentcategory.name}" description="#{componentcategory.description}" expanded="false" id="categoryForm">
<f:facet name="tools">
<b:commandButton look="link" styleClass="as-link" action="#{componentController.createComponent(componentcategory)}" value="#{msg.create_component}" title="#{msg.create_component}" size="md" iconAwesome="plus-circle" immediate="true" />
</f:facet>
<ul class="list-unstyled">
<ui:repeat value="#{componentcategory.componentList}" var="componentItem">
<li class="list-group-item">
<div class="row">
<div class="col-sm-7 name-col">#{componentItem.name}</div>
<div class="col-sm-5 text-right">
<b:buttonGroup>
<p:commandButton styleClass="btn btn-link as-link" style="float: left;" value="#{msg.copy_component}" title="#{msg.copy_component}" icon="fa fa-files-o" >
<p:ajax listener="#{componentController.sendComponentToCopy(componentItem)}" oncomplete="PF('copyComponentDialog').show()" process="panelRow:masterForm" partialSubmit="true" />
</p:commandButton>
</b:buttonGroup>
</div>
</div>
</li>
</ui:repeat>
<ui:fragment rendered="#{empty componentcategory.componentList}">
<li class="list-group-item list-group-item-info">#{msg.no_components_available}</li>
</ui:fragment>
</ul>
</bal:panel>
</ui:repeat>
<ui:fragment rendered="#{empty componentController.getComponentcategoryListByCompany(loginController.company)}">
<ul class="list-unstyled">
<li class="list-group-item list-group-item-info">#{msg.no_categories_available}</li>
</ul>
</ui:fragment>
</h:form>
</bal:row>
<p:dialog id="dlg" widgetVar="copyComponentDialog" resizable="false" draggable="false" showEffect="fade" hideEffect="fade" modal="true">
<h:form id="dlgForm" prependId="false">
<bal:panel id="copy_component_view" title="#{msg.copy_component}" styleClass="form-panel" collapsible="false">
<b:message for="name" showSummary="false"/>
<b:inputText value="#{componentController.copiedComponentName}" id="name" label="#{msg.name}" fieldSize="sm" required="true" requiredMessage="#{msg.name_required}" />
<bal:panel id="buttons">
<bal:row id="row" colStyleClass="btn-group">
<ui:remove>
<!-- Required works - After saving panels are no longer toggleable - JSF-lifecycle called twice -->
<p:commandButton value="#{msg.save}" styleClass="btn btn-primary" icon="fa fa-check">
<p:ajax listener="#{componentController.copyComponent()}" partialSubmit="true" process="copy_component_view" update="copy_component_view :panelRow:masterForm" oncomplete="if(!args.validationFailed) PF('copyComponentDialog').hide()" />
</p:commandButton>
<!-- Required doesn't work - After saving panels are toggleable, but view not updated - JSF-lifecycle called twice -->
<p:commandButton value="#{msg.save}" styleClass="btn btn-primary" icon="fa fa-check" ajax="false">
<p:ajax listener="#{componentController.copyComponent()}" partialSubmit="true" process="copy_component_view" update="copy_component_view :panelRow:masterForm" oncomplete="if(!args.validationFailed) PF('copyComponentDialog').hide()" />
</p:commandButton>
<!-- Required works - After saving panels are no longer toggleable - JSF-lifecycle called twice -->
<p:commandButton value="#{msg.save}" styleClass="btn btn-primary" icon="fa fa-check" actionListener="#{componentController.copyComponent()}" partialSubmit="true" process="copy_component_view" update="copy_component_view :panelRow:masterForm" oncomplete="if(!args.validationFailed) PF('copyComponentDialog').hide()" />
<!-- Required works - After saving panels are no longer toggleable - JSF-lifecycle called once -->
<p:commandButton value="#{msg.save}" styleClass="btn btn-primary" icon="fa fa-check" action="#{componentController.copyComponent()}" partialSubmit="true" process="copy_component_view" update="copy_component_view :panelRow:masterForm" oncomplete="if(!args.validationFailed) PF('copyComponentDialog').hide()" />
<!-- Required doesn't work - After saving panels are toggleable, view updated - JSF-lifecycle called once -->
<p:commandButton value="#{msg.save}" styleClass="btn btn-primary" icon="fa fa-check" ajax="false" action="#{componentController.copyComponent()}" partialSubmit="true" process="copy_component_view" update="copy_component_view :panelRow:masterForm" oncomplete="if(!args.validationFailed) PF('copyComponentDialog').hide()" />
<!-- Required works - After saving panels are no longer toggleable - JSF-lifecycle called once -->
<p:commandButton value="#{msg.save}" styleClass="btn btn-primary" icon="fa fa-check" partialSubmit="true" process="copy_component_view" update="copy_component_view :panelRow:masterForm" oncomplete="if(!args.validationFailed) PF('copyComponentDialog').hide()">
<f:actionListener binding="#{componentController.copyComponent()}" />
</p:commandButton>
<!-- Required doesn't work - After saving panels are toggleable, view updated - JSF-lifecycle called once -->
<p:commandButton value="#{msg.save}" styleClass="btn btn-primary" icon="fa fa-check" ajax="false" partialSubmit="true" process="copy_component_view" update="copy_component_view :panelRow:masterForm" oncomplete="if(!args.validationFailed) PF('copyComponentDialog').hide()">
<f:actionListener binding="#{componentController.copyComponent()}" />
</p:commandButton>
<!-- Required works - After saving panels are no longer toggleable - JSF-lifecycle called once -->
<p:commandButton value="#{msg.save}" styleClass="btn btn-primary" icon="fa fa-check" partialSubmit="true" process="copy_component_view" update="copy_component_view :panelRow:masterForm" oncomplete="if(!args.validationFailed) PF('copyComponentDialog').hide()">
<f:actionListener binding="#{componentController.copyComponent()}" />
</p:commandButton>
</ui:remove>
<!-- Required doesn't work- After saving panels are toggleable, view updated - JSF-lifecycle called once -->
<p:commandButton value="#{msg.save}" styleClass="btn btn-primary" icon="fa fa-check" ajax="false" actionListener="#{componentController.copyComponent()}" partialSubmit="true" process="copy_component_view" update="copy_component_view :panelRow:masterForm" oncomplete="if(!args.validationFailed) PF('copyComponentDialog').hide()" />
<b:commandButton value="#{msg.cancel}" iconAwesome="close" look="default" immediate="true" onclick="PF('copyComponentDialog').hide()" />
</bal:row>
</bal:panel>
</bal:panel>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>
</html>
修改 关于bal的更多信息:panel:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://xmlns.jcp.org/jsf/composite"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
<!-- INTERFACE -->
<cc:interface>
<cc:attribute name="title" type="java.lang.String" />
<cc:attribute name="description" type="java.lang.String" />
<cc:attribute name="subtitle" type="java.lang.String" />
<cc:attribute name="subtitle" type="java.lang.String" />
<cc:attribute name="leftFooter" type="java.lang.String"/>
<cc:attribute name="rightFooter" type="java.lang.String" />
<cc:attribute name="closable" type="java.lang.Boolean" default="false" />
<cc:attribute name="collapsible" type="java.lang.Boolean" default="true" />
<cc:attribute name="expanded" type="java.lang.Boolean" default="true" />
<cc:attribute name="styleClass" type="java.lang.String" />
<cc:attribute name="style" type="java.lang.String" />
<cc:attribute name="titleStyle" type="java.lang.String" />
<cc:attribute name="labelValue" />
<cc:attribute name="labelLook" default="plain"/>
<cc:attribute name="labelStyleClass" />
<cc:attribute name="labelStyle" />
<cc:facet name="tools" />
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<div id="#{cc.clientId}" class="ibox float-e-margins #{!cc.attrs.expanded?'border-bottom':''} #{cc.attrs.styleClass}" style="#{cc.attrs.style?cc.attrs.style:''}">
<ui:fragment rendered="#{not empty cc.attrs.title}">
<div class="ibox-title" style="#{not empty cc.attrs.titleStyle?cc.attrs.titleStyle:''}">
<span class="name-col">
<span>
<h5>#{cc.attrs.title}
<ui:fragment rendered="#{not empty cc.attrs.subtitle}">
<small class="m-l-sm">#{cc.attrs.subtitle}</small>
</ui:fragment>
<ui:fragment rendered="#{not empty cc.attrs.description}">
<h:outputLink value="" styleClass="ui-commandlink ui-widget btn-md">
<i class="fa fa-info-circle" data-toggle="tooltip" data-placement="auto" data-original-title="#{cc.attrs.description}" />
</h:outputLink>
</ui:fragment>
</h5>
<ui:fragment rendered="#{not empty cc.attrs.labelValue}">
<span class="label label-#{cc.attrs.labelLook} #{cc.attrs.labelStyleClass}" style="#{cc.attrs.labelStyle}">#{cc.attrs.labelValue}</span>
</ui:fragment>
</span>
</span>
<div class="ibox-tools">
<cc:renderFacet name="tools" />
<ui:fragment rendered="#{cc.attrs.collapsible eq true}">
<a class="collapse-link">
<i class="#{!cc.attrs.expanded?'fa fa-chevron-down':'fa fa-chevron-up'}"></i>
</a>
</ui:fragment>
<ui:fragment rendered="#{cc.attrs.closable eq true}">
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</ui:fragment>
</div>
</div>
</ui:fragment>
<c:if test="#{cc.childCount gt 0}">
<div class="ibox-content" style="display: #{!cc.attrs.expanded and cc.attrs.collapsible?'none':'block'};">
<cc:insertChildren />
</div>
</c:if>
<ui:fragment rendered="#{not empty cc.attrs.leftFooter or not empty cc.attrs.rightFooter}">
<div class="ibox-footer">
<ui:fragment rendered="#{not empty cc.attrs.rightFooter}">
<span class="pull-right">
#{cc.attrs.rightFooter}
</span>
</ui:fragment>
<ui:fragment rendered="#{not empty cc.attrs.leftFooter}">
#{cc.attrs.leftFooter}
</ui:fragment>
</div>
</ui:fragment>
</div>
</cc:implementation>
</html>
和bal:row:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://xmlns.jcp.org/jsf/composite">
<!-- INTERFACE -->
<cc:interface>
<cc:attribute name="colStyleClass" type="java.lang.String" />
<cc:attribute name="rowStyleClass" type="java.lang.String" />
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<div id="#{cc.clientId}" class="row #{cc.attrs.rowStyleClass}" >
<div class="col-lg-12 #{cc.attrs.colStyleClass}">
<cc:insertChildren />
</div>
</div>
</cc:implementation>
</html>