在表内以编程方式创建的JSF commandLink不起作用

时间:2019-01-20 06:16:30

标签: java jsf jsf-2

这可能吗?经过几个小时的战斗,我放弃了。

JSF表是通过编程方式创建的,并且也在内部创建了CommandLinks。

在表的内部和外部带有commandLink的代码段下面。两者的创建方式相似。 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:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">

<f:view contentType="text/html" locale="pl">
    <h:body>
        <h:form id="form">
            <h:dataTable binding="#{dynamicDataTable.table}" value="#{dynamicDataTable.tableContent}" />
            <!-- this one below works fine -->
            <h:commandLink binding="#{dynamicDataTable.link}" />
        </h:form>
    </h:body>   
</f:view>
</html>

DynamicDataTable bean:

@Named
@ViewScoped
public class DynamicDataTable implements Serializable {

    private static final long serialVersionUID = 1L;

    private HtmlDataTable table;
    private HtmlCommandLink link;
    private List<String> tableContent;

    public void action() {
        System.out.println("Action performed");
    }

    public HtmlDataTable getTable() {
        table = new HtmlDataTable();
        HtmlCommandLink inlink = new HtmlCommandLink();
        inlink.setValue("Inside link");
        inlink.setActionExpression(createMethodExpression("#{dynamicDataTable.action}", String.class));
        UIColumn column = new UIColumn();
        column.getChildren().add(inlink);
        table.getChildren().add(column);
        return table;
    }

    public List<String> getTableContent() {
        tableContent = new ArrayList<String>();
        tableContent.add("a");
        tableContent.add("b");
        return tableContent;
    }

    public void setTableContent(List<String> tableContent) {
        this.tableContent = tableContent;
    }

    public void setTable(HtmlDataTable table) {
        this.table = table;
    }

    public HtmlCommandLink getLink() {
        link = new HtmlCommandLink();
        link.setValue("Outside link");
        link.setActionExpression(createMethodExpression("#{dynamicDataTable.action}", String.class));
        return link;
    }

    public void setLink(HtmlCommandLink link) {
        this.link = link;
    }

    public static MethodExpression createMethodExpression(String expression, Class<?> returnType) {
        FacesContext context = FacesContext.getCurrentInstance();
        return context.getApplication().getExpressionFactory().createMethodExpression(
                context.getELContext(), expression, returnType, new Class[0]);
    }
}

表内的链接已创建,但不起作用。 在表外创建的一个,也可以通过编程方式创建。

有什么主意吗?

1 个答案:

答案 0 :(得分:1)

简要说明

您在上面遇到的问题是由于以下事实导致的:Viewhandler 无法处理您的操作链接,因为它无法为链接组件生成ID,这意味着对已激活的组件的引用实际上不见了。

您的两个示例实际上都不完全正确。但是,借助在表外部生成的链接,视图处理程序可以以某种方式找出该组件的ID,并在执行操作时以正确的位置结束。

查看代码

如果我们看一下调用上述代码时JSF Mojarra生成的内容,我们将看到以下内容:

表中的链接获取到form:j_idt3:0:j_id3的链接,但是没有ID归属于该组件,因此该链接将不起作用。

表外部的链接获取到form:j_idt5的链接,并生成ID j_id1:javax.faces.ViewState:0。因此,尽管确实确实调用了该操作-链接/ ID相关性并不完全正确。

因此,很明显,渲染器能够找出链接的生成ID,但是它永远不会将生成的ID设置到实际的组件/标签上。这有点问题。

解决问题

这里的解决方案是帮助JSF和视图处理程序通过操作找出组件的路径。您可以通过以编程方式生成命令链接时强制设置ID来实现此目的-在getTable()方法内,添加以下代码;

inlink.setId("link");

这应允许渲染器渲染具有工作动作链接的有效页面。