JSF: изменение стиля компонента в массиве jstl c: foreach не работает - PullRequest
1 голос
/ 27 августа 2010

Этот код отображает индекс и выполняет действие, используя тег <a4j:commandLink> 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"/>&#160;
           </c:forEach>
   </h:form>
  </rich:panel>
  <a4j:keepAlive beanName="testBean" />
    </body>
</html>

Обратите внимание, что он использует <a4j:keepalive>, чтобы поддерживать компонент поддержки между запросами Ajax.

Поддерживающий компонент (объем запроса):

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;

 }
}

Ответы [ 2 ]

1 голос
/ 31 августа 2010

Я всегда чувствую, что если я ссылаюсь на UIComponent в своем коде, я делаю что-то нелегкое.Вот как я это сделаю.

Попробуйте использовать <f:setPropertyActionListener> и <a4j:repeat> вместо actionListener и <c:forEach>.Кроме того, избегайте перерисовки целых форм, это вызывает проблемы в некоторых браузерах:

<h:panelGroup id="results">
  <a4j:repeat var="letterBean" items="#{testBean.letters}" >
    <a4j:commandLink id="letter" value="#{letterBean.letter}" reRender="results" styleClass="#{letterBean.selected ? 'selected' : 'unselected'}">
      <f:setPropertyActionListener value="#{letterBean}" target="#{testBean.selected}"/>
    </a4j:commandLink>&#160;
  </a4j:repeat>
</h:panelGroup>

Новый класс компонента:

public class LetterBean {
  private final String letter;
  private boolean selected;

  public LetterBean (String letter) {
    this.letter = letter;
  }

  //getters and setters

}

замените startWith на:

public void setSelected(LetterBean selectedBean) {
  for (LetterBean letter : letterBeans) {
    letter.setSelected(false);
  }
  selectedBean.setSelected(true);
}
0 голосов
/ 28 августа 2010

Я изменил код, изменив:

if (currentStartWithLetter != null) {
 valueExp = elFactory.createValueExpression(elContext, "unselected",Object.class);
 currentStartWithLetter.setValueExpression("styleClass", valueExp);
} 

на

if (currentStartWithLetter != null) {
 valueExp = elFactory.createValueExpression(elContext, "unselected",Object.class);
 currentStartWithLetter = (UIComponent) actionEvent.getComponent().findComponent(startLetter);
 currentStartWithLetter.setValueExpression("styleClass", valueExp);
} 

, и это работает.

Кажется, проблема в том, что currentStartWithLetter не относитсяк одному и тому же компоненту, потому что actionEvent отличается между вызовами.

...