2010-04-19 24 views
0

我在获取HtmlDataTable的数据模型被JSF 2.0和Facelets正确更新时遇到了问题。JSF 2.0:基于java的自定义组件+ html表格+ 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}"/> 

我的管理bean类包含以下

@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

你的问题很可能是在这里:

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); 

Here's an a project这表明JSF 2.0的程序使用。

+0

嗨,感谢您的建议,但是使用setValueExpression而不是setValue方法并没有解决问题。在提交表单时,数据模型不会更新。 有没有其他建议? – mikic 2010-04-20 08:56:42

+0

这是一个复杂的设置,很多事情可能会出错。我指出的无论如何都是一个问题。尝试跟踪/调试,在输入文本控制渲染器的解码方法中设置一个断点并从此处开始跟踪。 – lexicore 2010-04-20 10:25:30