2012-06-21 13 views
11

मैंने देखा कि यह सवाल पूछा गया था, लेकिन इसका सही उत्तर नहीं दिया गया है।जेएसएफ एच में क्रॉस फील्ड सत्यापन: पी का उपयोग कर डेटाटेबल: कैलेंडर

मैं एक datatable कि दो कॉलम प्रारंभ दिनांक और समाप्ति दिनांक है की है। दोनों में प्राइमफेस पी: कैलेंडर नियंत्रण शामिल हैं। मुझे यह सुनिश्चित करने की ज़रूरत है कि प्रत्येक पंक्ति के लिए कॉलम 1 में दिनांक कॉलम 2 की तारीख के बाद नहीं है। मैं इसे जेएसएफ सत्यापन ढांचे में जोड़ना चाहता हूं, लेकिन मुझे परेशानी हो रही है।

मैं datatable rowStatePreserved = "true" अंकन की कोशिश की है, यह मेरे मूल्यों को प्राप्त करने की अनुमति देता है, लेकिन कुछ अभी भी जब यह विफल के रूप में गलत है, पहली पंक्ति में सभी मूल्यों को अन्य सभी मान के ऊपर लिख। मैं गलत क्या कर रहा हूं, या क्या मुझे पूरी तरह से अलग रणनीति का उपयोग करना चाहिए?

एक्सएचटीएमएल कोड

<h:form> 
<f:event type="postValidate" listener="#{bean.doCrossFieldValidation}"/> 
     <p:dataTable id="eventDaysTable" value="#{course.courseSchedules}" var="_eventDay" styleClass="compactDataTable" 
           > 
         <p:column id="eventDayStartColumn"> 
          <f:facet name="header"> 
           Start 
          </f:facet> 
          <p:calendar id="startDate" required="true" value="#{_eventDay.startTime}" pattern="MM/dd/yyyy hh:mm a"/> 
         </p:column> 
         <p:column id="eventDayEndColumn"> 
          <f:facet name="header"> 
           End 
          </f:facet> 
          <p:calendar id="endDate" required="true" value="#{_eventDay.endTime}" pattern="MM/dd/yyyy hh:mm a"/> 
         </p:column>           
        </p:dataTable> 
     </h:form> 

validationCode

public void doCrossFieldValidation(ComponentSystemEvent cse) { 


     UIData eventsDaysStable = (UIData) cse.getComponent().findComponent("eventDaysTable"); 

     if (null != eventsDaysStable && eventsDaysStable.isRendered()) { 

      Iterator<UIComponent> startDateCalendarIterator = eventsDaysStable.findComponent("eventDayStartColumn").getChildren().iterator(); 
      Iterator<UIComponent> endDateCalendarIterator = eventsDaysStable.findComponent("eventDayEndColumn").getChildren().iterator(); 

      while (startDateCalendarIterator.hasNext() && endDateCalendarIterator.hasNext()) { 
       org.primefaces.component.calendar.Calendar startDateComponent = (org.primefaces.component.calendar.Calendar) startDateCalendarIterator.next(); 
       org.primefaces.component.calendar.Calendar endDateComponent = (org.primefaces.component.calendar.Calendar) endDateCalendarIterator.next(); 

       Date startDate = (Date) startDateComponent.getValue(); 
       Date endDate = (Date) endDateComponent.getValue(); 


       if (null != startDate && null != endDate && startDate.after(endDate)) { 
        eventScheduleChronologyOk = false; 
        startDateComponent.setValid(false); 
        endDateComponent.setValid(false); 
       } 

      } 

      if (!eventScheduleChronologyOk) { 
       showErrorMessage(ProductManagementMessage.PRODUCT_SCHEDULE_OUT_OF_ORDER); 
      } 

     } 

    } 

उत्तर

17

क्या मैं एक गैर मानक JSF में datatable के संदर्भ से बाहर गलत

प्रदर्शन सत्यापन कर रहा हूँ मार्ग। पंक्ति डेटा केवल उपलब्ध है जबकि आप (या जेएसएफ है) डेटाटेबल पर फिर से चल रहे हैं। मौजूदा डेटाटेबल पुनरावृत्ति दौर के आधार पर प्रत्येक कॉलम में भौतिक रूप से केवल एक <p:calendar> घटक है जिसमें कई अलग-अलग राज्य हैं। उन राज्यों में उपलब्ध नहीं हैं जब आप डेटाटेबल पर पुनरावृत्ति नहीं कर रहे हैं। आपको तब मूल्य के रूप में केवल null मिलेगा।

तकनीकी तौर पर, अपने अलग अलग मान्यता दृष्टिकोण के साथ अब तक, आप UIData घटक पर visitTree() विधि लागू किया जाना चाहिए और VisitCallback कार्यान्वयन में काम किया। यह डेटाटेबल पर फिर से शुरू होगा।

उदाहरण के लिए,

dataTable.visitTree(VisitContext.createVisitContext(), new VisitCallback() { 
    @Override 
    public VisitResult visit(VisitContext context, UIComponent component) { 
     // Check if component is instance of <p:calendar> and collect its value by its ID. 

     return VisitResult.ACCEPT; 
    } 
}); 

यह केवल अनाड़ी है। यह आपको हर पंक्ति देता है, आपको पंक्ति सूचकांक को बनाए रखने और जांचने और मूल्यों को एकत्र करने की आवश्यकता होगी। ध्यान दें कि UIInput#setValid() पर कॉल करना VisitCallback कार्यान्वयन के अंदर भी किया जाना चाहिए।


या मैं एक पूरी तरह से अलग रणनीति का प्रयोग किया जाना चाहिए?

हाँ, एक सामान्य Validator मानक JSF तरह से इस्तेमाल करते हैं। आप एक घटक को अन्य घटक की विशेषता के रूप में पारित कर सकते हैं।

उदा।

<p:column> 
    <p:calendar binding="#{startDateComponent}" id="startDate" required="true" value="#{item.start}" pattern="MM/dd/yyyy hh:mm a"/> 
</p:column> 
<p:column > 
    <p:calendar id="endDate" required="true" value="#{item.end}" pattern="MM/dd/yyyy hh:mm a"> 
     <f:validator validatorId="dateRangeValidator" /> 
     <f:attribute name="startDateComponent" value="#{startDateComponent}" /> 
    </p:calendar> 
</p:column>           

@FacesValidator("dateRangeValidator") 
public class DateRangeValidator implements Validator { 

    @Override 
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { 
     if (value == null) { 
      return; // Let required="true" handle. 
     } 

     UIInput startDateComponent = (UIInput) component.getAttributes().get("startDateComponent"); 

     if (!startDateComponent.isValid()) { 
      return; // Already invalidated. Don't care about it then. 
     } 

     Date startDate = (Date) startDateComponent.getValue(); 

     if (startDate == null) { 
      return; // Let required="true" handle. 
     } 

     Date endDate = (Date) value; 

     if (startDate.after(endDate)) { 
      startDateComponent.setValid(false); 
      throw new ValidatorException(new FacesMessage(
       FacesMessage.SEVERITY_ERROR, "Start date may not be after end date.", null)); 
     } 
    } 

} 

साथ दोनों घटकों एक ही पंक्ति में हैं, startDateComponent "स्वतः" सही मूल्य getValue() हर पर वापस इस सत्यापनकर्ता शुरू हो जाती है दे देंगे। ध्यान दें कि आपका प्रारंभिक दृष्टिकोण नहीं है, जबकि यह वैधकर्ता डेटाटेबल के बाहर भी पुन: प्रयोज्य है।

वैकल्पिक रूप से, आप एक पूर्ण समाधान के रूप में OmniFaces<o:validateOrder> का उपयोग कर सकते हैं। इसका showcase उदाहरण घटकों के <p:dataTable> के अंदर इस विशिष्ट उपयोग केस को भी दिखाता है।

+2

बिल्कुल मुझे क्या चाहिए –

+0

आपका स्वागत है। – BalusC

+0

@ बाल्लूसी क्रॉस-फील्ड और क्रॉस-पंक्ति सत्यापन को सत्यापित करने की रणनीति क्या होनी चाहिए? –