JSF 2.0: пользовательский компонент на основе Java + HTML-таблица + Facelets = модель данных не обновляется - PullRequest
1 голос
/ 19 апреля 2010

У меня возникают проблемы с корректным обновлением модели данных HtmlDataTable с помощью JSF 2.0 и Facelets.

Я создал пользовательский компонент на основе Java, который расширяет HtmlDataTable и динамически добавляет столбцы в методе encodeBegin.

@Override
public void encodeBegin(FacesContext context) throws IOException
{
  if (this.findComponent("c0") == null)
  {
    for (int i = 0; i < 3; i++)
    {
      HtmlColumn myNewCol = new HtmlColumn();
      myNewCol.setId("c" + i);
      HtmlInputText myNewText = new HtmlInputText();
      myNewText.setId("t" + i);
      myNewText.setValue("#{row[" + i + "]}");
      myNewCol.getChildren().add(myNewText);
      this.getChildren().add(myNewCol);
    }
  }
  super.encodeBegin(context);
}

Моя тестовая страница содержит следующее

    <h:form id="fromtb">
      <test:MatrixTest id="tb" var="row" value="#{MyManagedBean.model}">
      </test:MatrixTest>
      <h:commandButton id="btn" value="Set" action="#{MyManagedBean.mergeInput}"/>
    </h:form>
    <h:outputText id="mergedInput" value="#{MyManagedBean.mergedInput}"/>

Мой класс управляемых бинов содержит

@ManagedBean(name="MyManagedBean")
@SessionScoped
public class MyManagedBean 
{
private List model = null;
private String mergedInput = null;

public MyManagedBean() {
  model = new ArrayList();
  List myFirst = new ArrayList();
  myFirst.add("");
  myFirst.add("");
  myFirst.add("");
  model.add(myFirst);
  List mySecond = new ArrayList();
  mySecond.add("");
  mySecond.add("");
  mySecond.add("");
  model.add(mySecond);
}

public String mergeInput()
{
  StringBuffer myMergedInput = new StringBuffer();
  for (Object object : model)
  {
    myMergedInput.append(object);
  }
  setMergedInput(myMergedInput.toString());
  return null;
}

public List getModel() {
  return model;
}

public void setModel(List model) {
  this.model = model;
}

public String getMergedInput() {
  return mergedInput;
}

public void setMergedInput(String mergedInput) {
  this.mergedInput = mergedInput;
}

При вызове страница корректно отображается с таблицей, состоящей из 3 столбцов (добавленных во время выполнения) и 2 строк (так как моя модель данных имеет 2 строки). Однако, когда пользователь вводит некоторые данные в поля ввода и затем нажимает кнопку отправки, модель обновляется неправильно, и поэтому метод mergeInput () создает последовательность пустых строк, которая отображается на той же странице.

Я добавил некоторые записи в метод decode () моего пользовательского компонента и вижу, что параметры, введенные пользователем, отправляются обратно вместе с запросом, однако эти параметры не используются для обновления данных. модель .

Если я обновлю метод encodeBegin () моего пользовательского компонента следующим образом

@Override
public void encodeBegin(FacesContext context) throws IOException
{
  super.encodeBegin(context);
}

и я обновляю тестовую страницу следующим образом

    <test:MatrixTest id="tb" var="row" value="#{MyManagedBean.model}">
      <h:column id="c0"><h:inputText id="t0" value="#{row[0]}"/></h:column>
      <h:column id="c1"><h:inputText id="t1" value="#{row[1]}"/></h:column>
      <h:column id="c2"><h:inputText id="t2" value="#{row[2]}"/></h:column>
    </test:MatrixTest>

страница отображается правильно, и на этот раз, когда пользователь вводит данные и отправляет форму, базовая модель данных корректно обновляется, а метод mergeInput () создает последовательность строк с пользовательскими данными.

Почему тестовый пример со столбцами, объявленными на странице Facelet, работает правильно (то есть модель данных корректно обновляется JSF), где этого не происходит, когда столбцы создаются во время выполнения с помощью метода encodeBegin ()

Есть ли какой-нибудь метод, который мне нужно вызывать или интерфейс, который мне нужно расширить, чтобы обеспечить корректное обновление модели данных?

Я использую этот тестовый пример для решения проблемы, возникающей в гораздо более сложном компоненте, поэтому я не могу достичь той же функциональности, используя составной компонент Facelet.

Обратите внимание, что это было сделано с использованием NetBeans 6.8, JRE 1.6.0u18, GlassFish 3.0.

Спасибо за вашу помощь.

1 Ответ

1 голос
/ 19 апреля 2010

Ваша проблема, вероятно, здесь:

myNewText.setValue("#{row[" + i + "]}");

Здесь вы устанавливаете строковое значение, а не привязку значения. Вам нужно будет сделать что-то вроде:

Application application = facesContext.getApplication();
ExpressionFactory expressionFactory = application
        .getExpressionFactory();
...
ValueExpression valueExpression = expressionFactory
            .createValueExpression(facesContext.getELContext(),
                    "#{row[" + i + "]}", String.class);
myNewText.setValueExpression("value", valueExpression );

Вот проект , который демонстрирует программное использование JSF 2.0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...