h:outputLink with f:ajax - 调用方法,但链接未显示

时间:2011-07-29 06:37:48

标签: ajax jsf-2 facelets

这不起作用

<h:form style="display: inline;">
    <h:outputLink value="#{title.link}" >
        #{msg['g.readMore']}
        <f:ajax event="click" immediate="true" listener="#{titlesBean.titleClicked(title.id)}" />
    </h:outputLink>
</h:form>

我想要它做的是点击呼叫#{titlesBean.titleClicked(title.id)}然后转到链接。调用该方法但不会转到链接。还有其他几种方法(使用commandLink然后重定向,但我想知道为什么这不起作用)。

这是方法本身:

public String titleClicked(long titleId) {
    this.titlesManager.addXtoRating(titleId, 1);
    return null;
}

注意:这只是一个旁注,但我不小心发现这有效:

<script type="text/javascript">
    $('.share').popupWindow({centerBrowser:1,height:380,width:550});
</script>

<h:form style="display: inline;">
    <h:outputLink styleClass="share" value="http://www.facebook.com/sharer.php...">
        <img src="images/facebook-icon.jpg" />
        <f:ajax event="click" immediate="true" listener="#{titlesBean.titleLiked(title.id)}" />
    </h:outputLink>
 </h:form>

查看styleClass="share"

更新 :(我的代表不到100,所以我无法回答我自己的问题8小时,这就是如何巧妙地说 - 愚蠢)。 我等了一会儿,但没有人回答。

所以这是我的黑客攻击解决方案(我根本不喜欢它,但它有效):

<h:form style="display: inline;">
    <h:outputLink target="_blank" styleClass="click8" value="#{title.link}" >
        #{title.heading}
        <f:ajax event="click" immediate="true" listener="#{titlesBean.titleLiked(title.id)}" />
    </h:outputLink>
</h:form>

这是重要的部分:

<h:head>
    <script type="text/javascript">
        $(document).ready(function(){
            $('.click8').click(function (event){
                         var url = $(this).attr("href");
                         window.open(url, "_blank");
                         event.preventDefault();
            });
        });
    </script>
</h:head>

注意:这必须在标题中,否则我有一个主要的错误,链接打开一千个窗口。

1 个答案:

答案 0 :(得分:4)

它不起作用,因为这里存在竞争条件。在同一窗口中同时发送了两个HTTP请求。一个到服务器的ajax和一个与给定链接正常的ajax。越快完成的那个胜利。您想要同步发送HTTP请求。首先是ajax到服务器,当它返回时,然后正常的到给定链接。

至于你的hacky解决方案,它的工作原理是因为它使用JavaScript在新窗口中打开URL而不是当前的URL然后阻止链接的默认操作,因此正常响应只是到达一个完全独立的窗口而ajax响应仍然在初始窗口中到达。因此,在初始窗口中不再存在两个HTTP请求的竞争条件。

对于最终解决方案,使用标准的JSF 2.0组件集是不可能的。使用<h:commandLink>然后进行重定向确实可行,但链接这种方式不能被搜索机器人抓取,它会有效地触发POST请求,这比IMO更糟糕的是你的新窗口解决方案。

如果您真的想在当前窗口中打开链接,请将目标网址保留在链接的href中,然后我建议您创建一个简单的servlet来执行链接跟踪和重定向作业让jQuery在onclick期间操纵链接目标。

像这样的东西

<a rel="ext" id="ext_#{title.id}" href="#{title.link}">read more</a>

(HTML元素ID可能不以数字开头!因此ext_前缀,您当然可以根据需要改变它。)

$(function() {
    jQuery('a[rel=ext]').click(function(e) {
        var link = jQuery(this);
        var url = 'track'
            + '?id=' + encodeURIComponent(link.attr('id')) 
            + '&url=' + encodeURIComponent(link.attr('href'));

        if (link.attr('target') == '_blank') {
            window.open(url);
        } else {
            window.location = url;
        }

        e.preventDefault();
    });
});

@WebServlet(urlPatterns={"/track"})
public class TrackServlet extends HttpServlet {

    @EJB
    private TrackService trackService;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String id = request.getParameter("id");
        String url = request.getParameter("url");

        if (id == null || url == null) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }

        trackService.track(id.replaceAll("\\D+", "")); // Strips non-digits.
        response.sendRedirect(url);
    }

}