Есть ли способ не отправлять всю веб-форму при нажатии кнопки?

Я постараюсь быть максимально кратким, пожалуйста, оставайтесь со мной здесь

"A.jsf" -> управляемый компонент: bean "#{bean.list}": приведет нас к B.jsf

        <p:growl id="msgs" showDetail="true"/>
        <h:form id="myform1" enctype="multipart/form-data">
            <p:panel header="Upload" style="font-size: 11px;">
                <h:panelGrid columns="2" cellpadding="10">
                    <h:outputLabel value="Drawing:" />
                    <p:fileUpload fileUploadListener="#{bean.handleFileUpload}" update="msgs" allowTypes="*.*;"/>                        
                </h:panelGrid>
                <p:commandButton ajax="false" immediate="true" id="back" value="Back" action="#{bean.list}"/>
                <p:commandButton ajax="false" id="persist" value="Persist" action="#{bean.handleRevision}" />
            </p:panel>
        </h:form>

Затем handleFileUpload()

        if(!upload){
            FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", "You do not have permission to upload.");
            FacesContext.getCurrentInstance().addMessage(null, msg);
        }
        ...

"B.jsf" -> управляемый компонент: bean2

 ...
 <p:growl id="msgs" showDetail="true"/>
 ...

Когда я нажимаю «Загрузить», появляется сообщение об ошибке «У вас нет разрешения на загрузку», что хорошо. Но затем, когда я нажимаю «Назад», что приведет меня к B.jsf, я вижу рычащее сообщение «У вас нет разрешения на загрузку». опять таки. Кажется, что происходит, когда я нажимаю «Назад», я отправляю другой запрос формы для загрузки, который затем генерирует то же сообщение об ошибке, которое затем отображается в B.jsf. Есть ли способ исправить это, кроме того, чтобы поместить кнопку «Назад» в пустую форму, потому что теперь у меня есть две кнопки, стоящие друг над другом, а не рядом. Я пытаюсь сделать это:

FacesContext.getCurrentInstance().addMessage("tom", msg);

надеясь, что он отправит компонент с id="tom", поэтому рычание с id=msgs не загрузится, но не повезло. Я пытаюсь включить флаг upload, когда нажимаю кнопку Back, но веб-форма запрашивается до вызова метода, обрабатывающего навигацию back.

Это не так кратко, как хотелось бы, поэтому я хочу извиниться за это :D


person Thang Pham    schedule 24.08.2010    source источник


Ответы (2)


кроме размещения кнопки "Назад" в пустой форме, потому что теперь у меня есть две кнопки, стоящие друг над другом

HTML <form> по умолчанию является блочным элементом. Элементы блока HTML по умолчанию помещаются в новую строку. На самом деле вы хотите сделать его встроенным элементом. Вы можете сделать это, используя display: inline; в CSS.

Возвращаясь к реальной проблеме, меня, однако, удивляет, что метод fileUploadListener вызывается, несмотря на immediate="true" в p:commandButton. Я пытался воспроизвести это, и я могу это подтвердить. Но я бы не ожидал, что это произойдет. Обычно immediate="true" на кнопке является решением пропустить отправку "целой" формы (по крайней мере, пропустить UIInput компонентов без этого атрибута). Дальнейшее расследование показало мне, что p:fileUpload вообще не является компонентом UIInput и что прослушиватель запускается на этапе применения значений запроса, а не на этапе проверки или обновления значений модели. Таким образом, это поведение полностью предсказуемо, но все же является упущением в дизайне.

Поскольку p:fileUpload требует ajax="false" в компоненте p:commandButton, вы можете, с другой стороны, просто удалить его из кнопки «Назад», чтобы он запускал ajaxical запрос и, таким образом, пропускал вызываемый fileUploadListener.

person BalusC    schedule 25.08.2010
comment
Удаление ajax="false" на p:commandButton кнопки Back предотвращает вызов fileUploadListener, но также предотвращает navigation flow. В итоге кнопка Back никуда меня не ведет, а вот display:inline отлично работает, большое спасибо за потраченное на нее время, BalusC - person Thang Pham; 25.08.2010

На самом деле, придание кнопке другой формы звучит как отличное решение. Причина, по которой кнопки больше не выравниваются, заключается в том, что новый начальный элемент <form> начинается на отдельной строке. Вы должны быть в состоянии предотвратить это, добавив form { display: inline; } в свой файл CSS.

Тем не менее, если у вас есть оставшиеся сообщения об ошибках, от которых вы хотите избавиться, вы можете сделать это в методе инициализации вашего вспомогательного компонента (если он у вас есть). Следующие работы peachily:

public void clearErrorMessages() {
    //it may get messy to debug why messages are swallowed
    logger.debug("clearing messages, coming from " + new Exception().getStackTrace()[1]);

    Iterator iter = FacesContext.getCurrentInstance().getMessages();
    while (iter.hasNext()) {
        FacesMessage msg = (FacesMessage) iter.next();
        logger.debug("clearing message: " + msg.getDetail());
        iter.remove();
    }
}

Недостатком здесь является то, что любые ошибки, возникающие между отправкой формы и инициализацией вспомогательного компонента целевой страницы, также проглатываются.

person László van den Hoek    schedule 24.08.2010
comment
Спасибо. Я пробую этот <h:form style="margin:0;">Submit Button </h:form> <h:form> Back Button </h:form>, у меня еще два стоят друг на друге. Вы сказали, что метод clearErrorMessages() поместил его в метод инициализации целевого управляемого компонента, ну, мой целевой управляемый компонент имеет SessionScoped, поэтому конструктор будет вызываться только один раз при первой загрузке приложения, если только нет каких-либо аннотаций для обнаружения, когда страница перезагружается. - person Thang Pham; 25.08.2010