Метод прослушивания f: ajax в h: selectOneMenu не выполняется

#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 только в начале метода, чтобы убедиться, что он действительно не вызывается?