Детали обновления 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", я хочу визуализировать компонент 1, если renderu1 проверен, компонент2, если renderu2 cheked, и component3, если renderu3 отмечен
Мое текущее решение для этого - это функция js с использованием плагина jQuery forms:
$(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-адрес, ждет ответа, и если содержимое theres (код статуса не 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;
}
}
поэтому для exapmle, если установлен только 3-й флажок, ответ будет примерно таким:
<html>
<span id="u3" class="unique_container">
content of component3
</span>
</html>
его работая отлично, и его простые и все, но затем я начал использовать RichFaces для одного из моих компонентов - проблема в том, что он использует функцию jQuery $(document).ready(fn), и когда я перезагружаю часть с RichFaces, он разбивается (его компонент дерева и я не могу открыть узлы)
Я искал рабочее решение, которое может делать то, что у меня есть, но лучше подготовлено к проблемам с совместимостью (технически, я хочу решить, какую часть обновлять на основе параметров, поэтому, когда исходная страница отображается, я еще не знаю, что писать для атрибута "выполнить" и "отдать" )
Ответы
Ответ 1
Это на самом деле довольно ужасное решение. Вы можете решить это с помощью чистого JSF 2.0 без необходимости использования jQuery, JSTL и настраиваемых тегов. Вы можете использовать <f:ajax>
для запуска ajax-запроса и отображения частичных компонентов. Вы можете визуализировать компоненты JSF условно с помощью атрибута rendered
.
Здесь приведен пример базового запуска, предполагающий, что вы используете контейнер, поддерживающий Servlet 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;
}
}
Что все.