2016-09-07 75 views
1

我構建自定義JSF複合組件以輸入週期性。我有這個模型:JSF無法爲自定義複合輸入組件獲取渲染器

public class Periodicity implements Serializable { 

    private PeriodicityType type; 

    private Integer value = 0; 

    public PeriodicityExchange() { 
     super(); 
    } 

    /**Getter and setters**/ 

} 

哪裏PeriodicityType是包含DAYWEEKMONTHYEAR枚舉。

此模型的輸入組件由一個p:spinner元素組成,用於選擇一個數字值和一個h:selectOneMenu來選擇週期性類型。該組件效果很好,但現在我想有一個Java類的支持,所以我已經修改了我的facelet文件:

<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://xmlns.jcp.org/jsf/html" 
    xmlns:f="http://xmlns.jcp.org/jsf/core" 
    xmlns:composite="http://xmlns.jcp.org/jsf/composite" 
    xmlns:p="http://primefaces.org/ui"> 

<composite:interface componentType="periodicityInput"> 
    <composite:attribute name="value" type="model.Periodicity" /> 
</composite:interface> 

<composite:implementation> 
    <div class="col-xs-2"> 
     <p:spinner binding="#{cc.periodicityValue}" 
      value="#{cc.attrs.value.value}" min="0" /> 
    </div> 
    <div class="col-xs-3"> 
     <h:selectOneMenu binding="#{cc.periodicityType}" 
      value="#{cc.attrs.value.type}" styleClass="form-control"> 
      <f:selectItem itemLabel="No periodicity" noSelectionOption="true" /> 
      <f:selectItem itemLabel="Days" itemValue="DAY" /> 
      <f:selectItem itemLabel="Weeks" itemValue="WEEK" /> 
      <f:selectItem itemLabel="Months" itemValue="MONTH" /> 
      <f:selectItem itemLabel="Years" itemValue="YEAR" /> 
     </h:selectOneMenu> 
    </div> 
</composite:implementation> 

</html> 

這是我的java類(總部設在this BalusC's tutorial)。它使用faces-config.xml文件註冊爲一個組件:

public class PeriodicityInput extends UIInput implements NamingContainer { 

    private UIInput periodicityValue; 

    private UIInput periodicityType; 

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

    @Override 
    protected Object getConvertedValue(FacesContext context, Object newSubmittedValue) 
      throws ConverterException { 
     try { 
      return new PeriodicityExchange(
        Integer.parseInt(newSubmittedValue.toString().split("-")[0]), 
        newSubmittedValue.toString().split("-")[1]); 
     } catch (Exception ex) { 
      throw new ConverterException(ex); 
     } 
    } 

    public String getFamily() { 
     return COMPONENT_FAMILY; 
    } 

    public UIInput getPeriodicityType() { 
     return periodicityType; 
    } 

    public UIInput getPeriodicityValue() { 
     return periodicityValue; 
    } 

    @Override 
    public Object getSubmittedValue() { 
     return periodicityValue.getSubmittedValue() + "-" + periodicityType.getSubmittedValue(); 
    } 

    public void setPeriodicityType(UIInput periodicityType) { 
     this.periodicityType = periodicityType; 
    } 

    public void setPeriodicityValue(UIInput periodicityValue) { 
     this.periodicityValue = periodicityValue; 
    } 

} 

的問題是,當我使用componentType屬性我的組件到java類綁定,該組件停止渲染。 encodeBegin被調用,但做了一些進一步的調試,我注意到當JSF嘗試獲取複合組件的渲染器時,它將返回null。來自UIComponentBase類別的方法getRenderer(FacesContext)嘗試訪問context.getRenderKit().getRenderer(getFamily(), rendererType),其中家庭評估爲javax.faces.InputrendererTypejavax.faces.Composite

我正在使用Mojarra 2.2.12。我在這裏錯過了什麼?

回答

3

在家庭計算結果爲javax.faces.Input

這是不正確的。它應該是javax.faces.NamingContainer,常數值爲UINamingContainer.COMPONENT_FAMILY

以下COMPONENT_FAMILY與靜態導入重構過程中可能搞砸:

@Override 
public String getFamily() { 
    return COMPONENT_FAMILY; 
} 

上面實際上是從UIInput繼承,而它必須是UINamingContainer。最好用FQN來指定它。

@Override 
public String getFamily() { 
    return UINamingContainer.COMPONENT_FAMILY; 
} 
+0

哇,什麼趕!謝謝,Balus,在你的教程中指定像我這樣的無望複製粘貼者是很好的。順便說一下,是否可以在'getSubmittedValue'中返回空值?如果沒有選擇週期性類型,我會對整個週期性對象感興趣,但我想它可能與驗證階段相沖突。如果你想我可以發佈一個新的完整的問題或編輯這一個。 –

+0

我意識到它正確地寫在你的tuto中。完全是我的混亂,然後.. –

+2

不客氣。至於分拆問題,請在'getConvertedValue()'中執行空轉換作業。 – BalusC