h:commandLink无法在ui中工作:重复

时间:2012-09-16 09:44:05

标签: jsf

当用户点击包含该产品名称的链接时,我想显示有关产品的详细信息。

调试我的代码时,我发现下面代码中显示的details方法没有运行。

我的代码:

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:ui="http://java.sun.com/jsf/facelets">
<h:body>
    <ui:composition template="/Shared/layout.xhtml" >
        <ui:define name="title">Product</ui:define>
        <ui:define name="body">
            <div id="contents" >
                <h3> List Product in Site </h3>
                <ul>
                    <ui:repeat value="#{productBean.listProduct}" var="p">
                        <div id="list-item">
                            <div class='item' >
                                <div class='item-img' >
                                    <h:form>
                                        <input type="hidden" name="productId" value="#{p.productId}" />
                                        <h:commandLink action="#{productBean.details}">
                                            <h:graphicImage url="#{p.picture}" alt='No Picture' />
                                        </h:commandLink>
                                    </h:form>
                                </div>
                                <h:form>
                                    <input type="hidden" name="productId" value="#{p.productId}" />
                                    <h:commandLink value="#{p.name}" action="#{productBean}" >
                                    </h:commandLink>
                                </h:form>
                            </div>    
                        </div>
                    </ui:repeat>
                </ul>
                <h:form>
                    <h:commandLink value="text" action="#{productBean.test}">  <!-- test -->
                    </h:commandLink>
                </h:form>
            </div>
        </ui:define>
    </ui:composition>
</h:body>

的ProductBean:

@ManagedBean
@RequestScoped
public class ProductBean implements Serializable {

    private List<Products> listProduct;
    private List<Categories> listCategory;
    private Products product;

    public Products getProduct() {
        return product;
    }

    public void setProduct(Products product) {
        this.product = product;
    }

    public ProductBean() {
        listCategory = new ProductsDB().listCategory();
    }
    private int categoryId;

    public int getCategoryId() {
        return categoryId;
    }

    public void setCategoryId(int categoryId) {
        this.categoryId = categoryId;
    }

    public String listProductByCt() {
        try {
            String value = FacesContext.getCurrentInstance().
                    getExternalContext().getRequestParameterMap().get("categoryId");
            setCategoryId(Integer.parseInt(value));
            if (categoryId == 0) {
                return "index";
            }
            listProduct = new ProductsDB().listProducts(categoryId);
            return "product";
        } catch (Exception e) {
            return "error";
        }
    }

    public String details() {
        String s = "";
        try {
            String productId = FacesContext.getCurrentInstance().
                    getExternalContext().getRequestParameterMap().get("productId");
            if (productId != null) {
                product = new ProductsDB().getProductById(productId);
                return "details";
            }
        } catch (Exception e) {
            return "error";
        }
        return "error";
    }

    public String test()
    {
        return "s";
    }



    public List<Categories> getListCategory() {
        return listCategory;
    }

    public void setListCategory(List<Categories> listCategory) {
        this.listCategory = listCategory;
    }

    public List<Products> getListProduct() {
        return listProduct;
    }

    public void setListProduct(List<Products> listProduct) {
        this.listProduct = listProduct;
    }
}

我还尝试了另一种名为test的方法。这也是products.xhtml上的操作引用的,但该操作未放在<ui:repeat>内。在这种情况下,该方法确实会被执行。

测试方法:

public String test() {
    String productId = "IP16G";
    product = new ProductsDB().getProductById(productId);
    return "details";
}

2 个答案:

答案 0 :(得分:4)

您使用的是哪个版本的JSF?

您在ui:repeat中使用不同形式和隐藏输入显示的代码并不是真正惯用的JSF。您的第一个命令链接的操作中也存在拼写错误。它说produtBean,但我想它应该是productBean。如果你点击那个命令链接,JSF会给你一个例外。

你有这个例外,或者什么也没发生?

如果没有发生任何事情,可能的原因是用于呈现命令链接(#{productBean.listProduct})的数据在回发后不再可用。您使用什么方法来获取此数据以及Bean的范围是什么?在许多情况下,您应该使用@ViewScoped并在请求回发时初始化数据。

此外,请确保默认情况下没有<ui:repeat>的父组件具有设置为false的呈现属性。如果此属性在生命周期的某个时刻将设置为true,则可能在此之后 - 处理链接上的点击。如果发生这种情况,在处理点击时它仍然是false,这会导致它被无声地忽略。

您可以将测试命令链接放在<ui:repeat>

旁边,以测试最后的效果
<ui:repeat value="#{productBean.products}" var="product">
    ...
</ui:repeat>
<h:commandLink value="test" action="#{productBean.test}" />

虽然您使用多个表单和隐藏字段的方法确实有效,但更惯用的JSF版本将是:

<h:form>
    <ui:repeat value="#{productBean.products}" var="product">
        <h:commandLink action="#{productBean.details(product)}">
            <h:graphicImage url="#{product.picture}" alt="No Picture" />
        </h:commandLink>

        <h:commandLink value="#{product.name}" action="#{productBean.details(product)}" />
    </ui:repeat>
</h:form>

使用bean的details方法:

public String details(Product product) {
    this.product = product;
    return "details";
}

(获取更多偏离主题的内容,但如果您的所有方法都返回导航案例,则可能需要考虑使用<h:link>等直接链接,并将产品的ID作为参数。这将使用GET转到目标页面,在这种情况下更清洁)

修改

为了测试问题是否不在其他地方,请尝试以下代码。它是一个页面和一个支持bean。将这些添加到您的项目并请求页面。这应该有用。

forminloop.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">

    <h:body>

        <ui:repeat value="#{formInLoopBacking.items}" var="item">
            <h:form>
                <h:commandLink value="#{item}" action="#{formInLoopBacking.action}"/>
            </h:form>
        </ui:repeat>

    </h:body>
</html>

FormInLoopBacking.java

import javax.faces.bean.ManagedBean;

@ManagedBean
public class FormInLoopBacking {

    private String[] items = {"A", "B"};

    public String[] getItems() {
        return items;
    }

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

}

答案 1 :(得分:0)

查看上面的代码

您已打开<ui:repeat>标记,但未将其关闭,并尝试将整个<ui:repeat>放入表单中,并在<h:form>内检查您的网页是h:form标记。如果它不起作用,那么检查你的bean是否在视图范围内,如果没有放入视图范围。