有時,當使用<h:commandLink>
, <h:commandButton>
或<f:ajax>
,與標籤關聯的action
, actionListener
或listener
方法根本不會被調用。 或者,不使用提交的UIInput
值更新Bean屬性。 javascript
有哪些可能的緣由和解決方案? html
儘管個人回答並不是100%適用,可是大多數搜索引擎都將其做爲第一匹配,但我仍是決定將其發佈: java
若是您使用的是PrimeFaces (或相似的API) p:commandButton
或p:commandLink
,則可能忘記了將process="@this"
顯式添加到命令組件中。 jquery
如《 PrimeFaces用戶指南》第3.18節所述, process
和update
的默認值均爲@form
,這與您可能從純JSF f:ajax
或RichFaces中得到的默認值徹底相反,它們是execute="@this"
和render="@none"
分別爲render="@none"
。 git
只是花了我很長一段時間才能找到答案。 (...並且我認爲使用不一樣於JSF的默認值至關不明智!) github
我本身陷入了這個問題,並找到了致使該問題的另外一個緣由。 若是在後備bean中沒有用於* .xhtml中使用的屬性的setter方法,那麼就不會調用該操做。 web
每當UICommand
組件( <h:commandXxx>
, <p:commandXxx>
等)沒法調用關聯的操做方法,或者UIInput
組件( <h:inputXxx>
, <p:inputXxxx>
等)沒法處理提交值和/或更新模型值,而且在服務器日誌中看不到任何可谷歌搜索的異常和/或警告,一樣,按照JSF ajax請求中的異常處理配置ajax異常處理程序時,也沒有設置在web.xml
中的上下文參數下面, ajax
<context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param>
而且您也沒有在瀏覽器的JavaScript控制檯中看到任何可谷歌搜索的錯誤和/或警告(按Chrome / Firefox23 + / IE9 +中的F12打開Web開發人員工具集,而後打開「 控制檯」選項卡),而後在可能的緣由列表下進行工做。 數據庫
UICommand
和UIInput
組件必須放置在UIForm
組件內,例如<h:form>
(所以不是普通的HTML <form>
),不然什麼也不能發送到服務器。 UICommand
組件也不能具備type="button"
屬性,不然它將是一個無效按鈕,僅對JavaScript onclick
有用。 另請參見如何在JSF bean中發送表單輸入值和調用方法,而且<h:commandButton>不會啓動回發 。 api
您不能相互嵌套多個UIForm
組件。 這在HTML中是非法的。 瀏覽器行爲未指定。 小心包含文件! 您能夠並行使用UIForm
組件,可是在提交期間它們不會相互處理。 您還應該提防「上帝形態」反模式; 確保您不會無心間以相同的形式處理/驗證全部其餘(不可見的)輸入(例如,具備與輸入相同形式的隱藏對話框的隱藏對話框)。 另請參見如何在JSF頁面中使用<h:form>? 單一表格? 多種形式? 嵌套表格? 。
沒有應該發生UIInput
值驗證/轉換錯誤。 您可使用<h:messages>
顯示任何輸入特定的<h:message>
組件未顯示的<h:message>
。 不要忘記在<f:ajax render>
包含<h:messages>
的id
(若是有的話),以便在ajax請求中也將對其進行更新。 另請參見當按下p:commandButton時,h:messages不顯示消息 。
若是UICommand
或UIInput
元件放置等的迭代組件內<h:dataTable>
, <ui:repeat>
等,則須要確保徹底相同的value
的迭代成分的過程當中應用的請求的值相被保存表單提交請求。 JSF將在其上重申以找到單擊的連接/按鈕和提交的輸入值。 將bean放在視圖範圍內和/或確保將數據模型加載到bean的@PostConstruct
中(所以不在getter方法中!)應該能夠修復它。 另請參見如何以及什麼時候從數據庫中爲h:dataTable加載模型 。
若是動態源(如<ui:include src="#{bean.include}">
包含UICommand
或UIInput
組件,則須要確保在視圖期間保留徹底相同的#{bean.include}
值。表單提交請求的構建時間。 JSF將在構建組件樹期間從新執行它。 將bean放在視圖範圍內和/或確保將數據模型加載到bean的@PostConstruct
中(所以不在getter方法中!)應該能夠修復它。 另請參閱如何經過導航菜單Ajax刷新動態包含內容? (JSF SPA) 。
在表單提交請求的應用請求值階段,組件及其全部父項的rendered
屬性以及任何父項<c:if>
/ <c:when>
的test
屬性不該評估爲false
。 JSF將對其進行從新檢查,以做爲防範被篡改/被黑客入侵的保護措施的一部分。 將負責該條件的變量存儲在@ViewScoped
Bean中,或者確保您在@RequestScoped
Bean的@PostConstruct
中正確地@ViewScoped
初始化了該條件,能夠對其進行修復。 這一樣適用於組件的disabled
屬性,在應用請求值階段,該屬性不該評估爲true
。 另請參見未調用JSF CommandButton操做,而且不處理有條件呈現的組件中的Form Submit 。
該onclick
的屬性UICommand
組件和onsubmit
的屬性UIForm
組件不該該返回false
或致使JavaScript錯誤。 若是<h:commandLink>
或<f:ajax>
也應該在瀏覽器的JS控制檯中沒有可見的JS錯誤。 一般,使用Google搜索確切的錯誤消息已經能夠給您答案。 另請參見將jQuery添加到PrimeFaces會致使Uncaught TypeErrors 。
若是您經過JSF 2.x <f:ajax>
或例如PrimeFaces <p:commandXxx>
使用Ajax,請確保主模板中有<h:head>
而不是<head>
。 不然,JSF將沒法自動包含包含Ajax函數的必要JavaScript文件。 這將致使瀏覽器的JS控制檯出現JavaScript錯誤,例如「未定義mojarra」或「未定義PrimeFaces」。 另請參見與f:ajax和ui:repeat一塊兒使用時,不會調用h:commandLink actionlistener 。
若是您使用的是Ajax,而且提交的值最終爲null
,那麼請確保感興趣的UIInput
和UICommand
組件被<f:ajax execute>
或例如<p:commandXxx process>
覆蓋,不然它們將不會被'將被執行/處理。 另請參見在將<f:ajax>添加到<h:commandButton>並瞭解PrimeFaces流程/更新和JSF f:ajax執行/渲染屬性 時,模型中未更新提交表單值 。
若是提交的值仍然最終爲null
,而且您正在使用CDI管理Bean,請確保從正確的包中導入範圍註釋,不然CDI將默認爲@Dependent
,這樣能夠在每次評估時有效地從新建立Bean。 EL表達式 另請參見@SessionScoped bean一直釋放做用域並一直從新建立,字段變爲空,而且JSF 2應用程序中的默認Managed Bean Scope是什麼?
若是具備UICommand
按鈕的<h:form>
的UICommand
是事先由來自同一頁面中另外一種表單的ajax請求呈現/更新的,則第一個操做在JSF 2.2或更早版本中將始終失敗。 第二步和後續操做將起做用。 這是由視圖狀態處理中的錯誤引發的,該錯誤報告爲JSF規範問題790 ,當前已在JSF 2.3中修復。 對於較舊的JSF版本,您須要在<f:ajax>
的render
中顯式指定<h:form>
的ID。 另請參見h:commandButton / h:commandLink在第一次單擊時不起做用,僅在第二次單擊時起做用 。
若是<h:form>
設置了enctype="multipart/form-data"
以支持文件上傳,那麼您須要確保至少使用JSF 2.2,或者要確保負責該工做的servlet過濾器解析multipart / form-data請求的配置正確,不然FacesServlet
最終將根本沒有任何請求參數,從而沒法應用請求值。 如何配置此類過濾器取決於所使用的文件上傳組件。 對於「戰斧」 <t:inputFileUpload>
,請檢查此答案 ;對於PrimeFaces <p:fileUpload>
,請檢查此答案 。 或者,若是您實際上根本沒有上傳文件,請徹底刪除該屬性。
確保actionListener
的ActionEvent
參數是javax.faces.event.ActionEvent
,所以不是java.awt.event.ActionEvent
,這是大多數IDE建議的第一種自動完成選項。 若是使用actionListener="#{bean.method}"
則沒有參數也是錯誤的。 若是您不想在方法中使用參數,請使用actionListener="#{bean.method()}"
。 或者,也許您其實是想使用action
而不是actionListener
。 另請參見action和actionListener之間的區別 。
確保例如經過調用FacesContext#renderResponse()
或FacesContext#responseComplete()
,請求-響應鏈中的PhaseListener
或任何EventListener
沒有更改JSF生命週期以跳過調用操做階段。
確保同一請求-響應鏈中沒有Filter
或Servlet
以某種方式阻止了FacesServlet
的請求。
若是您使用的是PrimeFaces <p:dialog>
或<p:overlayPanel>
,請確保它們具備本身的<h:form>
。 由於,默認狀況下,JavaScript將這些組件重定位到HTML <body>
末尾。 所以,若是他們最初坐在<form>
,那麼如今他們將再也不坐在<form>
。 另請參閱p:commandbutton動做在p:dialog中不起做用
框架中的錯誤。 例如,當使用帶有defaultLabel
屬性的rich:calendar
UI元素(或在某些狀況下,是rich:placeholder
子元素)時,RichFaces會出現「 轉換錯誤 」。 當沒有爲日曆日期設置任何值時,此錯誤阻止Bean方法被調用。 跟蹤框架的錯誤能夠經過從一個簡單的工做示例開始並備份頁面直到發現該錯誤來完成。
萬一您仍然卡住,該進行調試了。 在客戶端,按Web瀏覽器中的F12打開Web開發人員工具集。 單擊控制檯選項卡,以便查看JavaScript。 它應該沒有任何JavaScript錯誤。 下面的屏幕快照是Chrome的示例,演示了在未聲明<h:head>
的狀況下提交啓用<f:ajax>
按鈕的狀況(如以上第7點所述)。
單擊網絡選項卡以查看HTTP流量監視器。 提交表單並調查請求標題和表單數據以及響應正文是否符合預期。 下面的屏幕快照是一個來自Chrome的示例,該示例演示了一個簡單表單的成功ajax提交,該表單具備一個<h:inputText>
和一個<h:commandButton>
以及一個<f:ajax execute="@form" render="@form">
。
(警告:當您在生產環境中從上述HTTP請求標頭髮布屏幕截圖時,請確保對屏幕截圖中的全部會話cookie進行加擾/模糊處理,以免會話劫持攻擊!)
在服務器端,請確保服務器以調試模式啓動。 將調試斷點放在感興趣的JSF組件的方法中,您但願在處理表單提交期間調用該方法。 例如,若是使用UICommand
組件, UICommand#queueEvent()
;若是使用UIInput
組件, UICommand#queueEvent()
UIInput#validate()
。 只需逐步執行代碼並檢查流程和變量是否符合預期便可。 屏幕截圖下方是Eclipse調試器的示例。
我還要提到與Primefaces的p:commandButton
有關的另外一件事!
當對服務器上須要執行的操做使用p:commandButton
,不能使用type="button"
由於它用於用於執行自定義javascript而不會引發ajax / non-ajax請求的按鈕到服務器。
爲此,您能夠分配type
屬性(默認值爲"submit"
),也能夠顯式使用type="submit"
。
但願這會對某人有所幫助!
最近,我遇到了一個問題,即便用IBM Extended Faces Components的JSF 1.2應用程序中沒有調用UICommand。
我在數據表的行上有一個命令按鈕(擴展版本,因此<hx:datatable>
),UICommand不會從表中的某些行觸發(不會觸發的行是大於默認行的行)顯示屏尺寸)。
我有一個下拉組件,用於選擇要顯示的行數。 支持該字段的值在RequestScope
。 支持表自己的數據在某種ViewScope
(實際上,臨時在SessionScope
)。
若是經過控件增長了行顯示,該值也綁定到了數據表的rows
屬性,則單擊此命令後,因爲此更改而顯示的全部行都不會觸發UICommand。
將此屬性放在與表數據自己相同的做用域中能夠解決此問題。
我認爲在上面的BalusC#4中已經提到了這一點,但不只表值須要在View或Session範圍內,並且還須要控制在該表上顯示的行數的屬性。