我的xhtml分为菜单区域(defaultMenu.xhtml)和内容区域(defaultContent.xhtml)。
defaultMenu.xhtml的代码是:
<h:form id="defaultmenuform">
<p:outputPanel id="menupanel" class="contain auto-fixed-center">
<p:panel id="pmenu" visible="#{phController.user.menuVisible}">
<table id="stutable">
<tr>
<td width="15%">
<p:outputLabel id="stuname" value="#{phController.phBean.studentName}" />
</td>
<td>
<p:tabMenu activeIndex="#{param.selectedtab}">
<p:menuitem value="Home" outcome="phome" icon="ui-icon-star">
<f:param name="selectedtab" value="0" />
</p:menuitem>
<p:menuitem value="Bank" outcome="bhome" icon="ui-icon-person">
<f:param name="selectedtab" value="1" />
</p:menuitem>
</p:tabMenu>
</td>
</tr>
</table>
</p:panel>
</p:outputPanel>
</h:form>
defaultContent.xhtml实际显示ph.xhtml内容(作为功能导航的一部分),代码为:
<ui:define name="content">
<f:event listener="#{phController.readPeople}" type="preRenderView">
</f:event>
<h:form id="form">
<p:selectOneRadio id="selstud" value="#{phController.phBean.ssSeq}" layout="custom">
<p:ajax update=":defaultmenuform:parentmenupanel :defaultmenuform:stuname" listener="#{phController.onChangePerson}"/>
<f:selectItems value="#{phController.selectStudents}" />
</p:selectOneRadio>
<div style="width: 300px; float:left;">
<p:dataGrid var="studentlist" value="#{phController.listStudent}" columns="1" rowIndexVar="stuindex">
<p:panel header="" style="text-align:left">
<h:panelGrid columns="1" style="width:100%">
<h:outputText value="#{studentlist.studentName}" />
<p:radioButton for=":form:selstud" itemIndex="#{stuindex}"/> Select
</h:panelGrid>
</p:panel>
</p:dataGrid>
</div>
</h:form>
</ui:define>
支持bean的代码是:
Map<String, Object> studentparam = new HashMap<>();
studentparam.put("studentSeq", phBean.getSsSeq());
lS = getBaseDAOService().readStudent("readStudent", studentparam);
phBean.setStudentName(lS.get(0).getStudentFirstName() + " " + lS.get(0).getStudentLastName());
如您所见,我调用onChangeStu方法在defaultMenu.xhtml中显示所选的Student Name。我正在使用自定义布局p:phxhtml中的selectOneRadio和onClick尝试更新defaultMenu.xhtml中的p:outputLabel。
成功调用了backing bean方法,并且该值也在变量phController.phBean.studentName中设置,但更新不起作用。我还使用查看源检查并且id是“:defaultmenuform:stuname”,我也尝试更新菜单面板“:defaultmenuform:menupanel”,但这些都不起作用。
不确定如何解决此问题。请建议。
包括所有.xhtmls的结构
<h:body id="entirePageBody">
<div id="page">
<ui:insert name="header" >
<ui:include src="/template/defaultHeader.xhtml" />
</ui:insert>
<ui:insert name="menu" >
<ui:include src="/template/defaultMenu.xhtml" />
</ui:insert>
<div id="content_div" class="auto-fixed-center">
<div id="content_div_padding" class="content-block">
<ui:insert name="content" >
<ui:include src="/template/defaultContent.xhtml" />
<ui:debug hotkey="z" />
</ui:insert>
</div>
</div>
<ui:insert name="footer" >
<ui:include src="/template/defaultFooter.xhtml" />
</ui:insert>
</div>
</h:body>
PhController.java:
公共类PhController扩展BaseController实现Serializable {
private List<Stud> listStudent;
private List selectStudents;
SelectItem option;
private PhBean phBean;
private Boolean menuVisible;
int counter = 0;
public PhController() {
phBean = new PhBean();
}
public void readPeople() {
listStudent = new ArrayList<Stud>();
listStudent.add(new Stud(1, "John Miller"));
listStudent.add(new Stud(2, "Scott Jackson"));
selectStudents = new ArrayList();
option = new SelectItem(listStudent.get(0).getStudentSeq(), "Select");
selectStudents.add(option);
option = new SelectItem(listStudent.get(1).getStudentSeq(), "Select");
selectStudents.add(option);
phBean.setSsSeq(String.valueOf(1));
phBean.setSelectedName(listStudent.get(0).getStudentName());
menuVisible = true;
}
public void onChangePerson() {
phBean.setSelectedName(listStudent.get(1).getStudentName());
}
// Getters and Setters
}
PhBean.java:
公共类PhBean实现Serializable {
private String ssSeq;
private String studName; // Used to display the name in the Menu bar.
private String selectedName;
public PhBean() {
}
// Getters and Setters
}
答案 0 :(得分:0)
我要说在p:ajax
defaultContent.xhtml
中要更新的组件列表应该只用空格分隔,不能用逗号分隔 - 所以请尝试更改它:
update=":defaultmenuform:menupanel, :defaultmenuform:stuname"
到此:
update=":defaultmenuform:menupanel :defaultmenuform:stuname"
<强>更新强>
我更多地玩了这个并且可能找到了线索 - 请将以下代码添加到defaultmenuform
:
<p:messages autoUpdate="true" showDetail="true" />
这应该有助于我们跟踪验证失败的原因(如果验证失败是您的根本原因 - 正如我所说,我复制此问题的可能性相当有限。)
无论如何,当我在p:selectOneRadio中选择了一些项目时,会出现如下错误消息:
Conversion Error setting value 'test001.Student@4110c95c' for 'null Converter'.
根本原因在于这一行:
<p:selectOneRadio id="selstud" value="#{phController.phBean.ssSeq}" layout="custom">
p:selectOneRadio
只希望将String
作为value
传递 - 而ssSeq
很可能是另一种类型。尝试更改填充value
的方式,以确保它始终为String
- 可能是phBean
的不同属性,或者只是一个全新的String
属性。
注意:如果这没有帮助,也许您可以使用非常简单的示例来更新您的问题:phController
和phBean
如果我们要测试它们会是什么样子。
更新#2
因此,您已经解释了每次加载/刷新页面时都要调用phController.readPeople
的问题,而是每次Ajax请求都会加载它,从而覆盖这些值。
在你的PhController
(它是一个bean,对吧?会话作用域?)你可以添加这样的东西(为了便于阅读,省略了null
检查):
public void readPeopleOnGet() {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
HttpServletRequest req = (HttpServletRequest) ec.getRequest();
String reqMethod = req.getMethod();
if ("GET".equals(reqMethod)) {
readPeople();
}
}
使用上面的方法,你可以保留defaultContext.xhtml
的这一部分,只要它实际被调用(我假设是这样),只是改变了监听器方法:
<f:event listener="#{phController.readPeopleOnGet}" type="preRenderView">
</f:event>
对于页面的每个请求,仍会调用方法readPeopleOnGet
,但由于Ajax请求为POST
,因此只有在页面加载或刷新时才会调用readPeople
这可能不是一个“完全干净”的解决方案,但在我测试它时似乎正常工作。
更新#3
好吧,既然你使用了PrimeFaces,就可以通过这种方式识别Ajax:
public void readPeopleOnGet() {
RequestContext rc = RequestContext.getCurrentInstance();
if (!rc.isAjaxRequest()) {
readPeople();
}
}
但是如果我从最新的评论中得到你的观点,那么你只想在第一次加载页面时运行readPeople
- 所以下面的部分可能会更好。
如果PhController
实际上是一个bean,你没有回答,但我认为它是(你发布的代码中没有可见的注释)。您可以尝试制作@SessionScoped
:
@ManagedBean
@SessionScoped
public class PhController extends BaseController implements Serializable {
// the rest of the PhController goes here...
然后你可以在PhController
:
@PostConstruct
private void init() {
readPeople();
}
注释@PostConstruct
确保在创建bean之后只调用一次方法init
。您可以根据需要继续从其他位置调用方法readPeople
,同时删除<f:event ... />
和readPeopleOnGet
,因为这些将不再需要。