#ajax #jsf #jsf-2
#ajax #jsf #jsf-2
Вопрос:
Страница сгенерирована правильно с соответствующими значениями в управляемом компоненте, но события ajax в этих двух h: selectOneMenus не работают. Прослушиватель не вызывается. Ошибка должна быть где-то внутри тегов, но я ее не вижу.
<f:view>
<h:form>
<h:messages />
<h:panelGrid columns="3">
<h:outputLabel value="Choose your faculty: *" for="faculties" />
<h:selectOneMenu id="faculties" value="#{registrateStudent.selectedFaculty}" >
<f:ajax event="change" listener="#{registrateStudent.genSpecializations}" execute="faculties" render="specializations" />
<f:selectItems value="#{registrateStudent.listFaculty}" var="curFac" itemLabel="#{curFac.name}" itemValue="#{curFac}" />
</h:selectOneMenu>
<h:message id="message_faculties" for="faculties" />
<h:outputLabel value="Choose your specialization: *" for="specializations" />
<h:selectOneMenu id="specializations" value="#{registrateStudent.selectedSpecialization}" >
<f:selectItems value="#{registrateStudent.listSpecialization}" var="curSpec" itemLabel="#{curSpec.name}" itemValue="#{curSpec}"/>
</h:selectOneMenu>
<h:message id="message_specializations" for="specializations" />
Управляемый компонент:
@ManagedBean(name = "registrateStudent")
@ViewScoped
public class RegistrateStudent {
private Faculty selectedFaculty;
private List<Faculty> listFaculty;
private Specialization selectedSpecialization;
private List<Specialization> listSpecialization;
private boolean showSpecialization = false;
/** Creates a new instance of RegistrateStudent */
public RegistrateStudent() {
users = new Users();
System.out.println("poaposd1");
student = new Student();
}
@PostConstruct
public void init() {
listFaculty = ff.findAll();
if (listFaculty != null) {
selectedFaculty = listFaculty.get(0);
listSpecialization = sf.findByFaculty(selectedFaculty.getIdFaculty());
if (listSpecialization != null) {
selectedSpecialization = listSpecialization.get(0);
}
else {}
} else {}
}
public void genSpecializations(AjaxBehaviorEvent event) {
if (sf.findByFaculty(selectedFaculty.getIdFaculty()) != null) {
this.showSpecialization = true;
} else {
JsfUtil.addSuccessMessage("faculties", "We don't have specializations for such faculty");
}
}
}
Обновить:
Я обнаружил несколько интересных вещей:
<f:ajax>
тег не работает в <h:link>
, <h:selectOneMenu>
, <h:button>
, <h:commandButton>
render
. В этом случае неправильные значения в event
атрибуте не замечаются, но неправильное значение в ,, атрибуте генерирует ошибку.
<h:outputLabel>
, <h:inputText>
работайте с <f:ajax>
должным образом
Комментарии:
1. вы пробовали execute=»@this» вместо execute =»факультеты»?
Ответ №1:
<f:ajax>
Требуется jsf.js
, чтобы файл был включен в HTML <head>
. Он содержит все функции JS для выполнения магии JSF ajax.
Для достижения этого убедитесь, что вы используете <h:head>
вместо <head>
в главном шаблоне. Затем JSF автоматически включит туда необходимый <script>
элемент, указывающий на jsf.js
.
<!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"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Look, with h:head</title>
</h:head>
<h:body>
Put your content here.
</h:body>
</html>
Обратите внимание, что в немного приличном веб-браузере с немного приличным набором инструментов webdeveloper, таким как панель инструментов веб-разработчика в Firefox и / или Firebug, вы должны были сразу заметить ошибки JS, такие jsf is undefined
как при выполнении ajax-запроса. Это, по крайней мере, должно было дать повод для размышлений.
Обновление: согласно вашему обновлению
Я обнаружил несколько интересных вещей:
<f:ajax>
тег не работает в<h:link>
,<h:selectOneMenu>
,<h:button>
,<h:commandButton>
render
. В этом случае неправильные значения вevent
атрибуте не замечаются, но неправильное значение в ,, атрибуте генерирует ошибку.
<h:outputLabel>
,<h:inputText>
работайте с<f:ajax>
должным образом.
<h:link>
и <h:button>
предназначены только для запросов GET, а не для запросов POST. Однако он должен отлично работать с <h:selectOneMenu>
и <h:commandButton>
. Разве у вас нет дополнительного кода для полной картины, который вы опустили в вопросе для простоты? Какой JSF impl / version вы используете? Используете ли вы правильные библиотеки в classpath? Похоже, вы, должно быть, действительно что-то напутали.
Чтобы убедить вас (и себя) Я только что создал следующий тестовый набор для копирования и вставки
<!DOCTYPE html>
<html lang="en"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
>
<h:head>
<title>SO question 6089924</title>
</h:head>
<h:body>
<h:form>
<h:selectOneMenu value="#{bean.selected}">
<f:selectItem itemValue="#{null}" itemLabel="Select..." />
<f:selectItem itemValue="one" />
<f:selectItem itemValue="two" />
<f:selectItem itemValue="three" />
<f:ajax listener="#{bean.listener}" render="result" />
</h:selectOneMenu>
<h:commandButton value="commandButton" action="#{bean.submit}">
<f:ajax listener="#{bean.listener}" render="result" />
</h:commandButton>
<h:outputText id="result" value="#{bean.selected} #{bean.result}" />
<h:messages />
</h:form>
</h:body>
</html>
с помощью этого компонента
package com.example;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.AjaxBehaviorEvent;
@ManagedBean
@ViewScoped
public class Bean implements Serializable {
private String selected;
private String resu<
public void submit() {
System.out.println("submit");
}
public void listener(AjaxBehaviorEvent event) {
System.out.println("listener");
result = "called by " event.getComponent().getClass().getName();
}
public String getSelected() {
return selected;
}
public void setSelected(String selected) {
this.selected = selected;
}
public String getResult() {
return resu<
}
}
Он отлично работает с Mojarra 2.1.1 на Tomcat 7.0.12.
INFO: Starting Servlet Engine: Apache Tomcat/7.0.12
INFO: Initializing Mojarra 2.1.1 (FCS 20110408) for context '/playground'
Комментарии:
1. спасибо, например. я полагаю,
value="#{bean.selected}"
что он не отображается на свойство bean при перемещении<h:form>
тега под<h:selectOneMenu>
из-за запроса POST? и почему h: outputLabel не работает без h: формы, даже если элементы не находятся в этой h: форме?2.Элементы ввода HTML, такие как
<input>
,<select>
,<textarea>
должны входить в HTML<form>
, чтобы получить значения, отправленные на сервер. Та же история применима и к JSF (поскольку все, что он в основном делает, это генерирует кучу HTML). В вашем исходном фрагменте кода вопроса вы все сделали правильно. Все компоненты JSF, представляющие элементы ввода HTML, уже находятся в форме.<h:outputLabel>
Просто отображает HTML<label>
элемент, который не имеет значения ввода семантической формы. Однако вы можете привязать к нему действия onclick.3. @BalusC Я заметил, что при использовании #{null} «#{bean.listener}» вообще не выполняется, как мы это объясним? Рекомендуется ли представлять пустую выборку с помощью #{null}?
4. @BalusC когда я использую
itemValue=0
, вызывается метод, когда я устанавливаюitemValue
значение#{null}
, метод не выполняется (я тестировал с печатями на консоли). Я не думаю, что это имеет отношение к ссылке, которую вы опубликовали.
Ответ №2:
Будьте осторожны, если у вас есть теги f:metadata
и f:viewparam
, поскольку установщики параметров будут вызываться с каждым ajax-запросом.
Можете ли вы предоставить журнал ошибок, если есть какая-либо ошибка / исключение, которое генерируется при вызове ajax-вызова?
Комментарии:
1. нет никакой ошибки или исключения. Также я только что заметил, что когда я изменяю первый h: selectOneMenu, другой повторно отображается, как и должно быть, но прослушиватель по-прежнему не вызывается.
2. можете ли вы поместить System.out.println только в начале метода, чтобы убедиться, что он действительно не вызывается?