JSF2 Primefaces Введите код ключа = 13, не работающий с commandButton

Реальный вопрос: я пытаюсь понять взаимодействие между фрагментом javascript, который я нашел, и commandButton Primefaces. Фрагмент javascript назначается атрибуту onkeypress тега JSF h:form. У меня есть этот фрагмент, работающий на некоторых моих страницах, но не на других. Когда я попытался убрать ненужное, чтобы задать ЭТОТ вопрос, javascript полностью перестал работать.

Кажется, я чего-то не понимаю, так как этот код не работает. Обратите внимание, что код работает, если пользователь действительно нажимает кнопку. Я хочу, чтобы это работало, когда они нажимают клавишу Enter. Я убрал все, что мог, и лоботомировал рекомендации по стилю, чтобы сделать его короче.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>Tray Report</title>
        <h:outputStylesheet library="css" name="postalreports.css"  />
    </h:head>
    <h:body>
        <h:form id="thisform"  onkeypress="if (event.keyCode == 13) { document.getElementById('thisform:btn').click(); return false; }" > 
            <p:panel id="panel" header="Report For Days">  
                <p:messages id="messages" />  
                <p:inputText id ="days" value="#{trayBean.days}" >
                </p:inputText>
            </p:panel>
            <p:commandButton id="btn" value="RUN" actionListener="#{trayBean.run}"/>            
        </h:form>
    </h:body>
</html>
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean
@ViewScoped
public class TrayBean implements Serializable {
    private Integer days = 1;
    public TrayBean() {}
    public void run() {
        System.out.println("do something here");
    }
    public Integer getDays() {  return days; }
    public void setDays(Integer days) { this.days = days; }
}

P.S. Я также пробовал if (event.keyCode == 13) { this.submit(); }

ДОБАВЛЕНО ПОСЛЕ ДОПОЛНИТЕЛЬНЫХ ИССЛЕДОВАНИЙ: К моему большому огорчению, я нашел специальное решение для Primefaces, которое должен был найти раньше. Оказывается, JavaScript вообще не нужен, если просто добавить тег p:focus. Вот XHTML-файл, который действительно работает. Нет никаких изменений в бэк-бине.

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">

    <h:head>
        <title>Tray Report</title>
    </h:head>
    <h:body>
        <h:form id="thisform"> 
            <p:focus/>
            <p:panel id="panel" header="Report For Days">  
                <p:messages id="messages" />  
                <p:inputText id ="days" value="#{trayBean.days}" >
                </p:inputText>
            </p:panel>
            <p:commandButton id="btn" value="RUN" actionListener="#{trayBean.run}"/>            
        </h:form>
    </h:body>
</html>

Это позволит мне завершить анализ моей первоначальной проблемы (поскольку у меня есть тег p:focus на страницах, которые еще не работают), который я опубликую отдельно.


person Dean    schedule 25.07.2013    source источник


Ответы (1)


Поскольку PrimeFaces основан на jQuery, вы должны сэкономить время и использовать jQuery для регистрации обработчика ключей формы. Конечно, вы должны разрешить ввод для элементов, которые его поддерживают и не запускают (и не должны запускать) отправку формы. Если вы запретите ENTER в текстовых областях, вы будете сильно раздражать своих пользователей.

По моему опыту, нажатия клавиши недостаточно, вам также нужно обработать нажатие клавиши:

<script type="text/javascript">
$(document).ready(function () {
var handler = function(event){
        if (event.which == 13) {
            var el = event.target;
            if (/textarea/i.test(el.tagName) || /button/i.test(el.tagName))
                return true;
            if (/input/i.test(el.tagName) && /file/i.test(el.type))
                return true;
            if (_handler)
                setTimeout(_handler, 1);
            event.stopPropagation();
            return false;
        }
        return true;
};
$('form').keyup(handler).keypress(handler)
});
</script>

См. также эту тему: Как предотвратить нажатие клавиши ENTER для отправки веб-форма? для других вопросов, не связанных с первоначальными лицами.

person Danubian Sailor    schedule 26.07.2013
comment
Спасибо! Это отлично сработало с одной оговоркой для зеленых разработчиков javascript, таких как я. Я счел необходимым окружить функции // ‹![CDATA[ // ]]› при размещении на моей странице xhtml. - person Dean; 29.07.2013
comment
CDATA не понадобился, когда я переместил скрипт в отдельный файл JavaScript. - person Dean; 29.07.2013
comment
ПРОДОЛЖЕНИЕ: Приведенное выше решение (p: focus) не работает с некоторыми компонентами Primefaces. Я счел необходимым использовать тег defaultCommand, чтобы заставить SelectOneMenu работать, когда я использовал его вместо InputText выше. ‹p:commandButton id=значение кнопки=RUN actionListener=#{trayBean.run}/› ‹p:defaultCommand target=btn/› - person Dean; 29.07.2013
comment
Что именно не сработало? Что касается действия по умолчанию, то я управлял им через дополнительный обработчик, но были места, где действие по умолчанию не требовалось. В любом случае, я все еще улучшаю этот код, когда проблема обнаруживается. - person Danubian Sailor; 29.07.2013
comment
\@Lukasz Предоставленный вами код работал отлично. В процессе поиска я наткнулся на альтернативное решение, которое не требует JavaScript, но использует исключительно теги Primefaces. Компания предпочитает, чтобы я не использовал JavaScript без необходимости. Я обнаружил, что единственное, что нужно для того, чтобы исходный xhtml заработал, — это добавление тега Primefaces ‹p:focus›. Однако этот тег не будет работать, если я заменю поле InputText на SelectOneMenu. Я смог решить этот случай с помощью тега ‹p:defaultCommand›. - person Dean; 31.07.2013