JSF 2: как показать различный статус ajax на одном входе?

Я хотел бы проверить каждое поле в моей форме, когда каждое поле теряет фокус, когда это происходит, я бы хотел, чтобы эти действия происходили:

1) в правой части поля появляется изображение в формате .gif (для обозначения того, что система проверяет ввод пользователя)

2) по завершении появляется другой .gif (который зависит от ввода, например, 'success.gif' или 'error.gif') и сообщение с правой стороны.

Я не хочу использовать всплывающие окна или что-то в этом роде, пользователь потеряет удобство использования, и я не хочу этого.

Я пытаюсь сделать что-то вроде этого, вот что я сделал до сих пор:

<h:form id="form">
    <h:panelGrid columns="3" >
        <h:outputLabel for="first_name" value="First Name:" />
        <h:inputText id="first_name" value="#{register.bean.firstName}" >
            <f:ajax event="blur" render="m_first_name" />
        </h:inputText>

        <a4j:status name="ajaxStatus">
            <f:facet name="start">
                <h:graphicImage name="loader.gif" library="images" />
                <h:outputText value="Processing ..." />
            </f:facet>
        </a4j:status>

        <a4j:commandButton value="Register !" action="#{register.validateName}" status="ajaxStatus" />

    </h:panelGrid>
</h:form>

Я искал какое-то решение в Google, и я думаю,

<a:a4j ... >

мой лучший вариант из-за атрибутов onbegin и oncomplete. Есть ли какой-то атрибут в каком-то родном теге в JSF 2?

ОБНОВЛЕНИЕ: подход @BalusC:

<!DOCTYPE html>
<html lang="pt-br"
    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>Insert title here</title>

        <script type="text/javascript">

        function showProgress(data) {
            var inputElement = data.source; // The HTML DOM input element.
            var ajaxStatus = data.status; // Can be "begin", "success" and "complete"
            var messageForInputElement = document.getElementById(inputElement.id + "_message");

            switch (ajaxStatus) {
                case "begin": // This is called right before ajax request is been sent.
                    messageForInputElement.innerHTML = "validating...";
                    break;

                case "complete": // This is called right after ajax response is received.
                    messageForInputElement.innerHTML = "";
                    break;

                case "success": // This is called when ajax response is successfully processed.
                    if (messageForInputElement.innerHTML.length == 0) { // So, no message has been set.
                        messageForInputElement.innerHTML = "valid!";
                    }
                    break;
            }
        }
        </script>

    </h:head>

    <h:body>
        <h:form id="form">
            <h:panelGrid columns="3">
                <h:outputLabel for="first_name" value="First Name" />
                <h:inputText id="first_name" value="#{bean.firstName}" required="true">
                    <f:ajax event="blur" render="first_name_message" onevent="showProgress" />
                </h:inputText>
                <h:message id="first_name_message" for="first_name" />

                <h:panelGroup />
                <h:commandButton value="Submit" action="#{register.doSomething}">
                    <f:ajax execute="@form" render="@form" />
                </h:commandButton>
                <h:messages globalOnly="true" layout="table" />
            </h:panelGrid>
        </h:form>
    </h:body>
</html>

А это мой боб:

@ManageBean
@ViewScope
..

public void doSomething(){
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

person Valter Silva    schedule 12.08.2011    source источник


Ответы (1)


Атрибуты onbegin и oncomplete Ajax4jsf являются просто дополнительными абстракциями существующего атрибута onevent стандарта JSF2 <f:ajax>. Вам нужно только ввести дополнительный код JavaScript для достижения той же функциональности.

Вот пример запуска:

<h:form>
    <h:panelGrid columns="3">
        <h:outputLabel for="input1" value="Input 1" />
        <h:inputText id="input1" value="#{bean.input1}" required="true">
            <f:ajax event="blur" render="input1_message" onevent="showProgress" />
        </h:inputText>
        <h:message id="input1_message" for="input1" />

        <h:outputLabel for="input2" value="Input 2" />
        <h:inputText id="input2" value="#{bean.input2}" required="true">
            <f:ajax event="blur" render="input2_message" onevent="showProgress" />
        </h:inputText>
        <h:message id="input2_message" for="input2" />

        <h:panelGroup />
        <h:commandButton value="Submit" action="#{bean.submit}">
            <f:ajax execute="@form" render="@form" />
        </h:commandButton>
        <h:messages globalOnly="true" layout="table" />
    </h:panelGrid>
</h:form>

Вот базовый начальный пример функции showProgress. Аргумент data — это объект JS, свойства которого уже описаны в таблицах 14-4 и 14-3 документа JSF. спецификация.

function showProgress(data) {
    var inputElement = data.source; // The HTML DOM input element.
    var ajaxStatus = data.status; // Can be "begin", "success" and "complete"

    var messageForInputElement = document.getElementById(inputElement.id + "_message");

    switch (ajaxStatus) {
        case "begin": // This is called right before ajax request is been sent.
            messageForInputElement.innerHTML = "validating...";
            break;

        case "complete": // This is called right after ajax response is received.
            messageForInputElement.innerHTML = "";
            break;

        case "success": // This is called when ajax response is successfully processed.
            if (messageForInputElement.innerHTML.length == 0) { // So, no message has been set.
                messageForInputElement.innerHTML = "valid!";
            }
            break;
    }
}

Вы можете заменить innerHTML этого стартового примера, например, изображениями или добавить/удалить класс стиля CSS в элементе сообщения, который использует фоновые изображения CSS, и т. д. Это не совсем тривиально, чтобы обеспечить кроссбраузерную совместимость. Я бы предложил добавить туда немного jQuery.

По сути, атрибуты onbegin и oncomplete Ajax4jsf устраняют необходимость писать целую JS-функцию с switch для достижения желаемой функциональности. Вы можете просто напрямую сослаться на некоторые функции JavaScript, которые делают то же самое, что и строки внутри case операторов switch. Это просто дополнительная абстракция. Вы можете рассмотреть возможность его использования, чтобы свести к минимуму объем шаблонного кода.

person BalusC    schedule 12.08.2011
comment
Я попробовал ваш подход, но статус, который вы указали в JS, меняется слишком быстро. Это как если бы метод не дождался обработки bean-компонента. Извините, что поздно ответил, потому что я пытался решить эту проблему. я обновляю свой пост, чтобы показать вам, как я делаю. - person Valter Silva; 13.08.2011
comment
Вы просили применить это к проверке ввода, а не к методам действий. Чтобы также иметь прогресс для метода действия, просто добавьте еще один onevent к <f:ajax> командной кнопки с немного другой функцией JS. - person BalusC; 13.08.2011