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

发布于 2024-11-26 19:42:59 字数 2094 浏览 1 评论 0原文

这不起作用

<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"

Update< /strong>:(我的代表数不到 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>

注意:这必须位于标题中,否则我有一个重大错误,链接打开了一千个视窗。

This does not work

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

What I want it to do is when clicked to call #{titlesBean.titleClicked(title.id)} and then go to the link. The method is called but it doesn't go to the link. There are several other ways to do it (with commandLink and then a redirect, but I would like to know why this is not working).

This is the method itself:

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

Note: this is only a sidenote, but I accidentally found out that this works:

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

Check out the styleClass="share"

Update: (I have less than 100 rep, so I cannot answer my own question for 8 hours, this is how to put it delicately - stupid).
I waited for a while, but nobody answered.

So this is my hacked solution ( I don't like it at all, but it works):

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

And this is the important part:

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

Note: this has to be in the header, otherwise I had a major bug with the link opening a thousand windows.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

丶情人眼里出诗心の 2024-12-03 19:42:59

它不起作用,因为这里存在竞争条件。在同一个窗口中同时发送两个 HTTP 请求。一种 ajax 连接到服务器,另一种 ajax 连接到给定的链接。较早完成的获胜。您想要同步发送 HTTP 请求。首先将 ajax 发送到服务器,当它返回时,然后将普通的 ajax 发送到给定的链接。

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

至于最终的解决方案,这对于标准的 JSF 2.0 组件集是不可能的。使用 然后进行重定向确实是可行的,但是这种方式的链接无法被搜索机器人抓取,并且它会有效地触发 POST 请求,这在我看来比您的新窗口更糟糕解决方案。

如果您确实想在当前窗口中打开链接,从而将目标 URL 保留在链接的 href 中,那么我建议创建一个简单的 servlet,它执行链接跟踪和重定向工作,并让 jQuery 在 onclick 期间操作链接目标。

像这样的东西

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

您当然可以以任何您想要的方式更改它。)

$(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();
    });
});

(HTML元素ID可能不以数字开头!因此ext_前缀,

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

}

It does not work because there's means of a race condition here. Two HTTP requests are been sent simultaneously in the same window. One ajax to the server and one normal to the given link. The one which finishes sooner wins. You want to send the HTTP requests in sync. First the ajax one to the server and when it returns, then the normal one to the given link.

As to your hacky solution, it works because it uses JavaScript to open the URL in a new window instead of the current one and then blocks the link's default action, so the normal response just arrives in a completely separate window while the ajax response still arrives in the initial window. So there's no means of a race condition of two HTTP requests in the initial window anymore.

As to the final solution, this is not possible with standard set of JSF 2.0 components. Using <h:commandLink> and then doing a redirect is indeed doable, but the link is this way not crawlable by searchbots and it fires effectively a POST request, which is IMO more worse than your new window solution.

If you would really like to open the link in the current window, hereby keeping the target URL in the link's href, then I'd suggest to create a simple servlet which does the link tracking and redirecting job and let jQuery manipulate the link target during onclick.

Something like this

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

(HTML element IDs may not start with a digit! Hence the ext_ prefix, you can of course change this whatever way you want.)

with

$(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();
    });
});

and

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

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文