在 table 中以编程方式创建的 JSF commandLink 不起作用

JSF commandLink created programmatically inside table doesn't work

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

JSF table 是以编程方式创建的,内部也有 commandLinks。

下面一段代码在 table 的外部和内部带有 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]);
    }
}

table 中的链接已创建,但不起作用。 在 table 之外创建的那个也以编程方式创建的工作正常。

有什么想法吗?

简要说明

您在上面遇到的问题是由于视图处理程序 无法 处理您的操作 link 因为它无法为 link 组件 - 意味着实际上缺少对激活组件的引用。

你举的两个例子其实都不对。然而,由于 link 在 table 之外生成,视图处理程序能够以某种方式找出组件的 id,并在执行操作时在正确的位置结束。

看代码

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

table 中的 link 得到一个 link 到 form:j_idt3:0:j_id3 但没有 id 归于组件,所以 link 将不行。

table外面的link得到一个link到form:j_idt5,生成idj_id1:javax.faces.ViewState:0。因此,虽然它确实调用了操​​作 - link/id 相关性并不完全正确。

很明显,渲染器能够为 link 计算出生成的 ID,但它从未将生成的 ID 设置到实际的 component/tag 上。这有点问题。

解决问题

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

inlink.setId("link");

这应该允许呈现器呈现具有工作操作的有效页面 links。