JSF2 AJAX обновить детали на основе параметров запроса

Этот пример является своего рода крайним, и что я пытаюсь сделать, это не совсем это, но проще продемонстрировать мою проблему с этим

у меня есть страница с простым index.xhtml:

<html
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:mc="http://java.sun.com/jsf/composite/mc">
    ...
    <h:panelGroup id="u1" styleClass="unique_container">
        <mc:component1></mc:component1>
    </h:panelGroup>
    <h:panelGroup id="u2" styleClass="unique_container">
        <mc:component2></mc:component2>
    </h:panelGroup>
    <h:panelGroup id="u3" styleClass="unique_container">
        <mc:component3></mc:component3>
    </h:panelGroup>
    <form action="/faces/async.xhtml">
        <input type="checkbox" name="renderu1" />
        <input type="checkbox" name="renderu2" />
        <input type="checkbox" name="renderu1" />
        <input type="submit" value="render" />
    </form>
    ...
</html>

когда я нажимаю на кнопку "GO", я хочу визуализировать component1, если выбран renderu1, component2, если renderu2 отмечен, и component3, если renderu3 отмечен

мое текущее решение для этого - функция js, использующая плагин форм jQuery:

$(document).ready(function(){
    registerForms($(document));
});

function registerForms(rootElement)
{
    rootElement.find("form").submit(function() {
    // submit the form
    $(this).ajaxSubmit(function(data, textStatus) {
        if(textStatus == "notmodified")
            return;


        var tempDiv = $('<div></div>');
        tempDiv.css("display", "none");
        tempDiv.html(data);
        var newUniqueContainer;
        while((newUniqueContainer = tempDiv.find(".unique_container:first")).html() != null)
        {
            var oldUniqueContainer = $("#" + newUniqueContainer.attr("id") + ":first");
            oldUniqueContainer.empty();
            oldUniqueContainer.html(newUniqueContainer.html());
            registerForms(oldUniqueContainer);
            newUniqueContainer.remove();
        }
        tempDiv.remove();
    });
    // return false to prevent normal browser submit and page navigation
    return false;
    });
}

то, что он делает, всякий раз, когда я отправляю форму, он запускает ajax-запрос к указанному URL-адресу, ожидает ответа, и, если есть содержимое (код состояния не 304, поэтому он не "не изменен"), он получает данные, и заменяет содержимое в оригинальном "unique_containers" на новые данные

async.xhtml:

<html xmlns:mc="http://java.sun.com/jsf/composite/mc"
      xmlns:c="http://java.sun.com/jsp/jstl/core">
    <c:if test="#{asyncBean.render1}">
        <h:panelGroup id="u1" styleClass="unique_container">
            <mc:component1></mc:component1>
        </h:panelGroup>
    </c:if>
    <c:if test="#{asyncBean.render2}">
        <h:panelGroup id="u2" styleClass="unique_container">
            <mc:component2></mc:component2>
        </h:panelGroup>
    </c:if>
    <c:if test="#{asyncBean.render3}">
        <h:panelGroup id="u3" styleClass="unique_container">
            <mc:component3></mc:component3>
        </h:panelGroup>
    </c:if>
</html>

AsyncBean.java:

@ManagedBean(name="asyncBean")
@RequestScoped
public class AsyncBean {

    @ManagedProperty(value="#{param.renderu1}")
    private boolean render1;

    @ManagedProperty(value="#{param.renderu2}")
    private boolean render2;

    @ManagedProperty(value="#{param.renderu3}")
    private boolean render3;

    private boolean isRender1() {
        return render1;
    }

    private void setRender1(boolean render1) {
        this.render1 = render1;
    }

    private boolean isRender2() {
        return render2;
    }

    private void setRender2(boolean render2) {
        this.render2 = render2;
    }

    private boolean isRender3() {
        return render3;
    }

    private void setRender3(boolean render3) {
        this.render3 = render3;
    }
}

Так, например, если установлен только 3-й флажок, ответ будет примерно таким:

<html>
    <span id="u3" class="unique_container">
        content of component3
    </span>
</html>

он работает нормально, и все просто, но потом я начал использовать RichFaces для одного из моих компонентов - проблема в том, что он использует функцию jQuery $(document).ready(fn), а когда я перезагружаю деталь с помощью RichFaces, это ломается (его компонент дерева, и я не могу открыть узлы)

Я искал рабочее решение, которое может делать то же, что и мое, но лучше подготовлено к проблемам совместимости (технически я хочу решить, какую часть обновлять, основываясь на параметрах, поэтому, когда отображается исходная страница, я пока не знаю что писать в атрибуты "execute" и "render")

1 ответ

Решение

Это на самом деле довольно ужасное решение. Вы можете решить эту проблему с помощью чистого JSF 2.0 без необходимости использования jQuery, JSTL и пользовательских тегов. Ты можешь использовать <f:ajax> запустить запрос ajax и визуализировать частичные компоненты. Вы можете визуализировать компоненты JSF по их условию rendered приписывать.

Вот базовый начальный пример, предполагая, что вы используете контейнер с сервлетом 3.0 / EL 2.2 с /WEB-INF/web.xml заявлено в соответствии со спецификацией Servlet 3.0 (в противном случае .contains() не будет работать в EL, и вы должны написать пользовательскую функцию EL).

<!DOCTYPE html>
<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
>
    ...
    <h:panelGroup id="panels">
        <h:panelGroup rendered="#{bean.panels.contains('u1')}">
            panel one
        </h:panelGroup>
        <h:panelGroup rendered="#{bean.panels.contains('u2')}">
            panel two
        </h:panelGroup>
        <h:panelGroup rendered="#{bean.panels.contains('u3')}">
            panel three
        </h:panelGroup>
    </h:panelGroup>

    <h:form>
        <h:selectManyCheckbox value="#{bean.panels}">
            <f:selectItem itemValue="u1" />
            <f:selectItem itemValue="u2" />
            <f:selectItem itemValue="u3" />
            <f:ajax render=":panels" />
        </h:selectManyCheckbox>
    </h:form>
    ...
</html>

с

@ManagedBean
@RequestScoped
public class Bean {

    private List<String> panels;

    public List<String> getPanels() {
        return panels;
    }

    public void setPanels(List<String> panels) {
        this.panels = panels;
    }

}

Это все.

Другие вопросы по тегам