JSF2 "f: ajax render" рендерит больше указанного идентификатора - PullRequest
1 голос
/ 06 июля 2011

Я искал и пробовал разные вещи здесь и в Интернете; prependId, используя полные пути к идентификаторам (: form: panelid: компонентный вид) и другие.

Я все еще в замешательстве. Я все еще новичок JSF:)

Моя проблема в том, что все, что я указываю в части рендеринга f: ajax, не единственные части, которые "исполняются". Я имею в виду, что идентификатор, указанный в render, не будет отображаться на экране, но вызывается значение этого компонента.

Итак:

inputText's f: ajax render = outA event = blur

когда происходит размытие, вызывается геттер outA, и он перерисовывается, но также вызывается геттер других компонентов, но они не перерисовываются.

В частности, в свете приведенного ниже кода:

A) Когда val1 теряет фокус, это вызывает событие размытия, которое вызывает getValue1 () и перерисовывает outval1. Счастливый. Но getStuff () также вызывается (это происходит и для другого размытия, а также для btnCalc), но результат из getStuff () НЕ отображается в tblStuff dataTable. Почему?

Как это исправить, чтобы на событии размытия выполнялись только геттеры, релевантные компоненту render = ".."?

Должен ли я использовать разные разделы?

B) когда кнопка обновления нажата, она вызовет getStuff СНОВА, и теперь покажет новую dataTable / то есть те новые данные со ВСЕМ МНОГО ValueTO, которые были добавлены во время событий размытия и события щелчка btnReload.

C) Для любого события, названного в A, метод getStuff вызывается ровно 8 раз. т.е. щелкните внутри поля ввода, щелкните вне поля ввода, getStuff () * 8. И все же getValue1 вызывается только дважды?

D) Есть хорошие книги по JSF2?

Вот эта страница:

<?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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">

<h:head>
    <title>Stuff</title>
</h:head>
<h:body>
        <h:form id="frmTrxMain" prependId="true">

            <h1>
                Stuff
            </h1>

            <h:dataTable title="Stuff" id="tblStuff" var="s" value="#{bean.stuff}" border="1">

                <h:column>
                    <f:facet name="header">
                        <h:outputText value="ID" />
                    </f:facet>
                    <h:outputText value="#{s.id}"/>
                </h:column>

                <h:column>
                    <f:facet name="header">
                        <h:outputText value="Name" />
                    </f:facet>
                    <h:outputText value="#{s.name}" />
                </h:column>

            </h:dataTable>

            <h:outputText value="No stuff to display" rendered="#{empty bean.stuff}"/>
            <h:commandButton value="Refresh" id="btnReload">
                <f:ajax render="tblStuff" event="click"/>
            </h:commandButton>

            <hr/>

            <h:panelGrid columns="3" id="pnlTwo">
                <h:outputLabel value="Value1"/>
                <h:inputText value="#{bean.value1}" id="val1">
                    <f:ajax event="blur" render="outVal1"/>
                </h:inputText>
                <h:outputText id="outVal1" value="Entered: #{bean.value1}" />

                <h:outputLabel value="Value2"/>
                <h:inputText value="#{bean.value2}" id="val2">
                    <f:ajax event="blur" render="outVal2"/>
                </h:inputText>
                <h:outputText id="outVal2" value="Entered: #{bean.value2}" />

                <h:commandButton value="Calc" id="btnCalc"> 
                  <f:ajax event="click" render="outSum"/> 
                </h:commandButton> 
            </h:panelGrid>

            <h:outputLabel id="outSum" value="#{bean.sum}"/>
        </h:form>
</h:body>
</html>

И поддерживающий боб:

import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean(name = "bean")
@SessionScoped
public class TestStuffBean {

private int id=1;
private String name="a";
//test.xhtml
private String value1;
private String value2;

private List<TestVO> stuff = new ArrayList<TestVO>();

public String getValue1() {
    return value1;
}

public void setValue1(String value1) {
    this.value1 = value1;
}

public String getValue2() {
    return value2;
}

public void setValue2(String value2) {
    this.value2 = value2;
}

public String getSum() {

    String result = "";

    int sum;
        try {
            sum = Integer.parseInt(value1) + Integer.parseInt(value2);
            result = Integer.toString(sum);
        } catch (NumberFormatException e) {
            result = "Enter two integers";
        }

    return result;
}

public List<TestVO> getStuff() {
    //the VO is just a POJO with a contructor that takes 
            //two strings and a getter/setter for each id and name
        stuff.add(new TestVO(Integer.toString(id), name+id));
        id++;

    return stuff;
}
}

1 Ответ

0 голосов
/ 06 июля 2011

Я не эксперт JSF 2, так как мы все еще используем 1.2, но я предполагаю, что они имеют одинаковые свойства: геттеры часто вызываются, например, при восстановлении вида в фазе восстановления-просмотра. Таким образом, вы не можете полагаться на получателей, только вызванных для фактически отрисованной части. На самом деле, вы не должны делать никаких дорогостоящих операций (таких как доступ к базе данных) в своих методах получения - в большинстве случаев вы не знаете, как часто они фактически вызываются за один цикл.

Особенно ваш метод getStuff() должен быть изменен, также почти всегда плохой дизайн - иметь побочные эффекты, вызывающие геттер, например, добавление чего-либо во внутренний список, как в этом случае.

Редактировать: Чтобы уточнить комментарий к получателям:

Обычно получатель не должен выполнять дорогостоящие операции, так как вы не знаете, как часто JSF будет их вызывать. Поскольку вам все еще нужно получить некоторые данные из некоторого источника (например, из базы данных), вы можете предоставить методы, которые только делают это (например, loadDataFromDB()) и заполняют некоторую структуру данных в управляемом компоненте. Затем получатель может просто доставить эту структуру данных.

Вы можете добавить проверку на то, что структура данных не инициализируется, и если нет, вызвать метод загрузки в геттере, но я бы использовал это только в качестве последнего параметра. Как правило, вы должны иметь возможность отдельно вызывать метод загрузки, например, нажав кнопку обновления или при переходе на страницу - это то, что мы делаем.

...