7 Replies Latest reply on Dec 2, 2009 9:56 PM by Franck Garcia

    JSF required attribute

    Franck Garcia Newbie

      I would need to reset a SEAM EntityHome component when a required field is submitted with an empty value (ajax request). I have a JSF Validator on the input text but it seems that JSF does not call any Validator if there is no value in the input field!!! I was wondering how I could solve this, where can I hook to call my action in this situation (SEAM @Observer ?). Any help appreciated. Thanks,

        • 1. Re: JSF required attribute
          Arbi Sookazian Master

          What event would you observe?  You can create a custom Seam validator class as well.

          • 2. Re: JSF required attribute
            Franck Garcia Newbie

            I already have my SEAM Validator but it seems JSF does not trigger Validators if the value is empty. So checking for emptiness with validators is pointless, they will never be reached. I need to hook my code somewhere else but don't know where....Thanks

            • 3. Re: JSF required attribute
              Arbi Sookazian Master

              You could check in the form submit() method and handle it there or a helper class using FacesMessages instance and redirect back to same page with error...

              • 4. Re: JSF required attribute
                Nikos Paraskevopoulos Novice

                Hi,


                Triggering an action in response to a control taking a specific value (empty in your case) should not happen in a validator, in my opinion. You could try:



                1. a standard JSF valueChangeListener (it will run during a JSF phase before the Invoke Application phase, i.e. your action)

                2. a Seam page action (will run after Invoke Application, before rendering - if I remember well)

                3. a standard JSF PhaseListener specifically for the page in question, configured with <f:phaseListener> (will run before/after any phase you want)

                4. if you want conditional handling of the submitted data depending on the value of this field, the logic should probably go in the action method



                Could you describe your use case in more detail?

                • 5. Re: JSF required attribute
                  Franck Garcia Newbie

                  Thanks for your response. I think you're absolutely right when you say I should not mix validation with action so I'm going to explore the ValueChangeListener path to trigger my action which seems the most suitable in my case.


                  Here after my UC:



                  I've got a form to create/manage an Entity called 'Entry' that has FK to 'Carrier' and 'Importer'. Both Carrier and Importer are mapped to a single denormalized table called Party. I use the EntityHome SEAM framework feature for the entities and the PM.
                  The idea is that I want to let my user possibly enter a Carrier Code (not my PK but unique constraint in Party) through an input text (here after a snapshot of my carrier field) :


                  <s:decorate id="carrierField" template="layout/edit.xhtml">
                       <ui:define name="label">Carrier Code</ui:define>
                       <ui:param name="required" value="true"/>
                       <h:inputText id="carrierCode" value="#{carrierPartyHome.instance.carrierCode}"  validator="carrierCodeValidator" required="true">
                           <a:support event="onblur" reRender="carrierField" ajaxSingle="true" eventsQueue="carrier" ignoreDupResponses="true" requestDelay="1000"/>
                       </h:inputText>
                       <h:outputText value="#{carrierPartyHome.instance.name}"/>
                       <a:commandLink ajaxSingle="true" value="Search" action="#{pickParty.first(true)}" reRender="searchCarrier_searchResultPanel" oncomplete="Richfaces.showModalPanel('searchCarrier',{top:'169px',left:'650px',height:'300px'});">
                            <f:param name="partyType" value="CA"/>
                       </a:commandLink>
                  </s:decorate>
                  



                  Inside my carrierCodeValidator I validate vs. the table that the passed code is valid, if it is I set the carrierPartyHome.id to my query's result, if not I call the clearInstance method on it. Before rendering, the page action calls the wire() method on the EntryHome instance in order to bind the carrier to my entry. Problem is if my user reset the field after having a valid value my state is not synchronized on the server side.



                  I'm new to SEAM and JSF, did not touch Web programming since STRUTS 1.2 and I think SEAM is wonderful but I really have hard time right now to figure out how I should design my application. There are so many choices to do a single thing that I'm confused and I don't want to mess it up. With Struts and EJB2 with the MVC you were on rails (not on ruby's one though). I would definitely need a good book on designing Enterprise Application with SEAM and JSF, but beside explaining in detail the different frameworks features I could not find anything valuable. Thanks again!

                  • 6. Re: JSF required attribute
                    Nikos Paraskevopoulos Novice

                    Hello again,


                    Now I understand better. Does the form contain more than the above? Anyway I would suggest something like (ellipses where things dont change):


                    <s:decorate ...>
                         <ui:define ...>
                         <ui:param ...>
                         <h:inputText id="carrierCode" value="#{carrierPartyHome.instance.carrierCode}">
                             <a:support event="..." reRender="..." ajaxSingle="..." eventsQueue="..." ignoreDupResponses="..." action="#{carrierPartyHome.checkCarrierCode}" />
                         </h:inputText>
                         <h:outputText .../>
                         <a:commandLink ... disabled="#{!carrierPartyHome.carrierCodeValidated}">
                              <f:param .../>
                         </a:commandLink>
                    </s:decorate>
                    



                    I have added 2 things in carrierPartyHome, the property boolean carrierCodeValidated and the action method checkCarrierCode. The <h:inputText id="carrierCode"> is no longer JSF-required (so the Invoke Application phase will be called even if it is empty), has no JSF validator (it is irrelevant) and the AJAX delay is zero-or at least decreased (optionally).


                    carrierPartyHome.checkCarrierCode() performs the validation logic you described. The result of the validation goes to
                    carrierPartyHome.carrierCodeValidated, which, in turn, controls whether <a:commandLink action="#{pickParty.first(true)}"> is enabled.


                    It may need modifications, but I hope you get the idea. Good luck!

                    • 7. Re: JSF required attribute
                      Franck Garcia Newbie

                      Thanks for your time, I didn't even think of adding a method to my carrierPartyHome, and I think it make more sense to add it there.