h: outputLink с f: ajax - метод вызван, но ссылка не показана - PullRequest
3 голосов
/ 29 июля 2011

Это не работает

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

Примечание : это только sidenote, но я случайно обнаружил, что это работает:

<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 Ответ

4 голосов
/ 29 июля 2011

Это не работает, потому что здесь есть средство для состояния гонки.Два HTTP-запроса отправляются одновременно в одном и том же окне.Один ajax к серверу и один нормальный к данной ссылке.Тот, который заканчивается раньше, побеждает.Вы хотите отправлять HTTP-запросы синхронно.Сначала ajax на сервер, а когда он возвращает, , затем нормальный к данной ссылке.

Что касается вашего хакерского решения, оно работает, потому что использует JavaScript для открытия URL вновое окно вместо текущего и затем блокирует действие ссылки по умолчанию, поэтому обычный ответ просто приходит в совершенно отдельное окно, в то время как ответ ajax все еще приходит в исходное окно.Таким образом, в исходном окне больше нет условий состязания двух HTTP-запросов.

Что касается окончательного решения, это невозможно при стандартном наборе компонентов JSF 2.0.Использование <h:commandLink> и последующее перенаправление действительно выполнимо, но эта ссылка не может быть найдена поисковыми роботами, и она эффективно запускает POST-запрос, который на IMO хуже, чем ваше новое оконное решение.

Если вы действительно хотите открыть ссылку в текущем окне, сохраняя целевой URL-адрес в ссылке на ссылку, то я бы предложил создать простой сервлет , который выполняет ссылкуотслеживание и перенаправление задания, и пусть jQuery манипулирует целевым объектом ссылки во время onclick.

Примерно так:

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

(идентификаторы HTML-элементов могут начинаться не с цифры! Следовательно,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);
    }

}
...