2012-12-04 13 views
4

我把這個問題在一個簡單的例子,其計算的2個輸入的總和並輸出結果在的outputText如何防止多個複合組件在JSF頁面上自行重置?

主JSF頁複合部件:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ez="http://java.sun.com/jsf/composite/ezcomp/"> 
    <h:head></h:head> 
    <h:body> 
     <ez:Calculator /> 
     <br/> 
     <br/> 
     <ez:Calculator /> 
     <br/> 
     <br/> 
     <ez:Calculator /> 
    </h:body> 
</html> 

複合部件XHTML:

<!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:composite="http://java.sun.com/jsf/composite" 
    xmlns:h="http://java.sun.com/jsf/html"> 
    <h:head> 
     <title>This content will not be displayed</title> 
    </h:head> 
    <h:body> 
    <composite:interface componentType="calculator"> 
    </composite:interface> 

    <composite:implementation> 
     <h:form> 
     <h:inputText id="first" value="#{cc.firstNumber}" /> 
     <h:commandButton value="+" action="#{cc.sum}"/> 
     <h:inputText id="second" value="#{cc.secondNumber}" /> 
     </h:form> 
     <h:outputText id="result" value="#{cc.result}" /> 
    </composite:implementation> 

</h:body> 
</html> 

複合部件支持bean:

package ez; 


import javax.faces.component.FacesComponent; 
import javax.faces.component.UINamingContainer; 

@FacesComponent("calculator") 
public class Calculator extends UINamingContainer { 

    private Long firstNumber; 
    private Long secondNumber; 
    private Long result; 

    public Calculator() { 
    } 

    @Override 
    public String getFamily() { 
     return "javax.faces.NamingContainer"; 
    } 

    public void setFirstNumber(String firstNumber) { 
     this.firstNumber = Long.parseLong(firstNumber); 
    } 

    public String getFirstNumber() { 
     if(firstNumber == null) { 
     return null; 
     } 
     return firstNumber.toString(); 
    } 

    public void setSecondNumber(String secondNumber) { 
     this.secondNumber = Long.parseLong(secondNumber); 
    } 

    public String getSecondNumber() { 
     if(secondNumber == null) { 
     return null; 
     } 
     return secondNumber.toString(); 
    } 

    public String getResult() { 
     if(result == null) { 
     return null; 
     } 
     return result.toString(); 
    } 

    public void setResult(String result) { 
     this.result = Long.parseLong(result); 
    }  

    public void sum() { 
     this.result = this.firstNumber + this.secondNumber; 
    } 
} 

所以,我有3個複合組件都應該做同樣的事情,但是當我按下一個SUM按鈕時,在服務器處理完請求之後,結果會打印在頁面上,但其他兩個組件將被清除值。

我該如何預防?我如何強迫它保留這些值?

回答

7

UIComponent情況下,將重新創建在每次請求,自此失去所有的實例變量每次。它們基本上像請求範圍的託管bean一樣行動,而您打算將它們放在視圖範圍中。您需要在每個屬性的基礎上考慮視圖狀態保存。這通常默認已經爲#{cc.attrs}的所有屬性完成。所以,如果可以的話,只是利用它:

<cc:interface componentType="calculator"> 
    <cc:attribute name="firstNumber" type="java.lang.Long" /> 
    <cc:attribute name="secondNumber" type="java.lang.Long" /> 
</cc:interface> 
<cc:implementation> 
    <h:form> 
     <h:inputText id="first" value="#{cc.attrs.firstNumber}" /> 
     <h:commandButton value="+" action="#{cc.sum}"/> 
     <h:inputText id="second" value="#{cc.attrs.secondNumber}" /> 
    </h:form> 
    <h:outputText id="result" value="#{cc.attrs.result}" /> 
</cc:implementation> 

與眼前這個(略nullchecks,我建議就投入使用的required="true"

@FacesComponent("calculator") 
public class Calculator extends UINamingContainer { 

    public void sum() { 
     Long firstNumber = (Long) getAttributes().get("firstNumber"); 
     Long secondNumber = (Long) getAttributes().get("secondNumber"); 
     getAttributes().put("result", firstNumber + secondNumber); 
    } 

} 

否則,你必須通過將所有屬性獲取器/設置器委派給UIComponent#getStateHelper(),將自己的存儲自己保存到中。基於您所擁有的完全相同的Facelets代碼,整個支持組件將如下所示:

@FacesComponent("calculator") 
public class Calculator extends UINamingContainer { 

    public void sum() { 
     setResult(getFirstNumber() + getSecondNumber()); 
    } 

    public void setFirstNumber(Long firstNumber) { 
     getStateHelper().put("firstNumber", firstNumber); 
    } 

    public Long getFirstNumber() { 
     return (Long) getStateHelper().eval("firstNumber"); 
    } 

    public void setSecondNumber(Long secondNumber) { 
     getStateHelper().put("secondNumber", secondNumber); 
    } 

    public Long getSecondNumber() { 
     return (Long) getStateHelper().eval("secondNumber"); 
    } 

    public void setResult(Long result) { 
     getStateHelper().put("result", result); 
    } 

    public Long getResult() { 
     return (Long) getStateHelper().eval("result"); 
    } 

} 

請參閱,不再有局部變量。請注意,我還通過聲明正確的getter返回類型和setter參數類型來消除那些難看的手冊String-Long轉換的需要。 JSF/EL將基於默認轉換器或自定義Converter s自動進行轉換。由於Long已有一個默認值,因此不需要提供自定義Converter


無關的具體問題,您可以安全地刪除getFamily()方法。 UINamingContainer已經提供了這個。如果您正在實施NamingContainer界面,那麼您確實需要自己提供它,但在此情況並非如此。上述支持組件示例已將其刪除。

相關問題