JSF:更改 jstl c:foreach 数组中的组件样式不起作用
此代码显示索引并使用 RichFaces 的
标记执行操作。从技术上来说它工作得很好。只有先前选择的字母的样式没有被重置(尽管执行了适当的代码部分)。有谁知道问题出在哪里以及如何解决?
JSF 页面:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!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:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:c="http://java.sun.com/jstl/core" xmlns:rich="http://richfaces.org/rich" xmlns:a4j="http://richfaces.org/a4j">
<head>
<style>
a.selected {
text-decoration: underline;
}
a.unselected {
text-decoration: none;
}
</style>
</head>
<body>
<rich:panel id="result">
hello
<h:form id="myForm">
<c:forEach var="letter" items="#{testBean.letters}" >
<a4j:commandLink id="${letter}" value="${letter}" actionListener="#{testBean.startWith}" reRender="result" styleClass="unselected"/> 
</c:forEach>
</h:form>
</rich:panel>
<a4j:keepAlive beanName="testBean" />
</body>
</html>
请注意,它使用
来使支持 bean 在 Ajax 请求之间保持活动状态。
支持 bean(请求范围):
public class testBean
{
private String startLetter = null; // selects from alphabetical page
private String[] letters = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
private UIComponent currentStartWithLetter;
public void startWith(ActionEvent actionEvent)
{
FacesContext facesContext = FacesContext.getCurrentInstance();
ELContext elContext = facesContext.getELContext();
Application app = facesContext.getApplication();
ExpressionFactory elFactory = app.getExpressionFactory();
ValueExpression valueExp;
if (currentStartWithLetter != null) {
valueExp = elFactory.createValueExpression(elContext, "unselected",Object.class);
currentStartWithLetter.setValueExpression("styleClass", valueExp);
}
currentStartWithLetter = actionEvent.getComponent();
startLetter = currentStartWithLetter.getId();
valueExp = elFactory.createValueExpression(elContext, "selected",Object.class);
currentStartWithLetter.setValueExpression("styleClass", valueExp);
someAction(actionEvent);
}
public void setLetters(String[] letters) {
/* nothing to do */
}
public String[] getLetters() {
return letters;
}
public String getStartLetter() {
return startLetter;
}
public void setStartLetter(String startLetter) {
this.startLetter = startLetter;
}
}
This code displays an index and performs an action using RichFaces' <a4j:commandLink>
tag. It works technically fine. Only the style of previously selected letter is not been reset (altough the appropriate code part is executed). Does anybody know where the problem is and how to solve it?
The JSF page:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!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:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:c="http://java.sun.com/jstl/core" xmlns:rich="http://richfaces.org/rich" xmlns:a4j="http://richfaces.org/a4j">
<head>
<style>
a.selected {
text-decoration: underline;
}
a.unselected {
text-decoration: none;
}
</style>
</head>
<body>
<rich:panel id="result">
hello
<h:form id="myForm">
<c:forEach var="letter" items="#{testBean.letters}" >
<a4j:commandLink id="${letter}" value="${letter}" actionListener="#{testBean.startWith}" reRender="result" styleClass="unselected"/>
</c:forEach>
</h:form>
</rich:panel>
<a4j:keepAlive beanName="testBean" />
</body>
</html>
Note that it is using <a4j:keepalive>
to keep the backing bean alive between Ajax requests.
The backing bean (request scoped):
public class testBean
{
private String startLetter = null; // selects from alphabetical page
private String[] letters = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
private UIComponent currentStartWithLetter;
public void startWith(ActionEvent actionEvent)
{
FacesContext facesContext = FacesContext.getCurrentInstance();
ELContext elContext = facesContext.getELContext();
Application app = facesContext.getApplication();
ExpressionFactory elFactory = app.getExpressionFactory();
ValueExpression valueExp;
if (currentStartWithLetter != null) {
valueExp = elFactory.createValueExpression(elContext, "unselected",Object.class);
currentStartWithLetter.setValueExpression("styleClass", valueExp);
}
currentStartWithLetter = actionEvent.getComponent();
startLetter = currentStartWithLetter.getId();
valueExp = elFactory.createValueExpression(elContext, "selected",Object.class);
currentStartWithLetter.setValueExpression("styleClass", valueExp);
someAction(actionEvent);
}
public void setLetters(String[] letters) {
/* nothing to do */
}
public String[] getLetters() {
return letters;
}
public String getStartLetter() {
return startLetter;
}
public void setStartLetter(String startLetter) {
this.startLetter = startLetter;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我总觉得如果我在代码中引用
UIComponent
我正在做一些困难的事情。我就是这样做的。尝试使用
和
代替actionListener
和
。另外,避免重新渲染整个表单,它会在某些浏览器中导致问题:新 bean 类:
将
startWith
替换为:I always feel that if I'm referencing
UIComponent
in my code I'm doing something the hard way. Here's how I'd do this.Try using
<f:setPropertyActionListener>
and<a4j:repeat>
in place ofactionListener
and<c:forEach>
. Also, avoid rerendering whole forms, it causes issues in some browsers:New bean class:
replace
startWith
with:我修改了代码,将 :
更改为
并且它有效。
问题似乎是
currentStartWithLetter
不再引用相同的组件,因为调用之间的 actionEvent 不同。I modified the code changing :
into
and it works.
The problem seems to be that
currentStartWithLetter
does not refer to the same component anymore because the actionEvent is different between calls.