2016-02-17 8 views
12

का उपयोग करते समय आउटपुट के साथ शून्य या खाली तारों को बदलें, निम्नलिखित कनवर्टर मूल रूप से अग्रणी और पीछे की ओर सफेद रिक्त स्थान को ट्रिम करने और एक स्थान या पाठ में शब्दों के बीच एक से अधिक स्थान को प्रतिस्थापित करने का इरादा है। कनवर्टर अब null या "उपलब्ध नहीं" के साथ खाली तारों को बदलने के लिए संशोधित किया गया है (यदि आवश्यक हो तो गतिशील रूप से स्थानीयकृत किया जा सकता है)।किसी जेएसएफ कनवर्टर

@FacesConverter(forClass = String.class) 
public class StringTrimmer implements Converter { 

    @Override 
    public Object getAsObject(FacesContext context, UIComponent component, String value) { 
     return Boolean.TRUE.equals(component.getAttributes().get("skipConverter")) ? value : value == null ? null : value.trim().replaceAll("\\s+", " "); 
    } 

    @Override 
    public String getAsString(FacesContext context, UIComponent component, Object value) { 
     return Boolean.TRUE.equals(component.getAttributes().get("skipConverter")) ? value == null ? null : value.toString() : value == null || ((String) value).trim().length() == 0 ? "Not available" : ((String) value).trim().replaceAll("\\s+", " "); 
    } 
} 

कन्वर्टर्स के बाद से लागू नहीं कर रहे हैं, जब एक मॉडल मूल्य, null पर the previous question आधारित, com.sun.faces.renderkit.html_basic.TextRenderer लागू कन्वर्टर्स करने के इरादे से बढ़ा दिया गया है है जब जुड़े मॉडल में एक संपत्ति के मूल्य null है।

public final class HtmlBasicRenderer extends TextRenderer { 

    @Override 
    public String getCurrentValue(FacesContext context, UIComponent component) { 

     if (component instanceof UIInput) { 
      Object submittedValue = ((UIInput) component).getSubmittedValue(); 

      if (submittedValue != null) { 
       return submittedValue.toString(); 
      } 
     } 

     return getFormattedValue(context, component, getValue(component)); 
    } 
} 

following सशर्त परीक्षण हटा दिया गया है ताकि getFormattedValue() विधि लागू किया जा सकता है, भले ही एक null मूल्य का सामना करना पड़ा है। इस प्रकार

Object currentObj = getValue(component); 

if (currentObj != null) { 
    currentValue = getFormattedValue(context, component, currentObj); 
} 

यह faces-config.xml में पंजीकृत किया गया है।

<render-kit> 
    <renderer> 
     <component-family>javax.faces.Output</component-family> 
     <renderer-type>javax.faces.Text</renderer-type> 
     <renderer-class>com.example.renderer.HtmlBasicRenderer</renderer-class> 
    </renderer> 
</render-kit> 

कनवर्टर StringTrimmer अभी भी लागू नहीं किया गया है (getAsString()), जब लक्ष्य मॉडल में एक संपत्ति मान देता है null

ईएल में #{empty bean.value ? 'Not available' : bean.value} जैसे हर जगह एक सशर्त परीक्षण डालकर पागलपन है। कोई उपाय?

यह मोजररा 2.2.12 है।


अद्यतन: जब getFormattedValue() विधि के अंदर वापसी बयानों में से एक एक खाली स्ट्रिंग "", लौटने जब currentValuenull है, कॉल में एक परिवर्तित मान देने के लिए संशोधित किया गया है

परिवर्तित मूल्यों उपलब्ध हैं,

javax.​faces.​convert.​Converter.getAsString(FacesContext context, UIComponent component, Object value) 

उस विधि के अंदर getFormattedValue()

इस प्रकार, following,

if(currentValue == null) { 
    return ""; 
} 

से बदलने की जरूरत है,

if (currentValue == null) { 
    converter = Util.getConverterForClass("".getClass(), context); 
    return converter == null ? "" : converter.getAsString(context, component, currentValue); 
} 

(जरूरत सुझाव)।

+0

जिसमें घटक आप इस कोशिश कर रहे हैं (जब से तुम एक सामान्य रूप में बनाना 'forClass = String.class') यदि बस आउटपुट टेक्स्ट में, मैं एक साधारण कस्टम घटक का उपयोग करता हूं और डी को प्रतिस्थापित/प्रतिस्थापित करता हूं efault जेएसएफ या प्राइमफेस इस के साथ एक। – Kukeltje

+0

यह मूल रूप से '' है। कस्टम घटक चयनित वैकल्पिक फ़ील्ड के लिए बनाए जा सकते हैं लेकिन फिर किसी को ध्यान से याद रखने की आवश्यकता है कि कौन से फ़ील्ड शून्य या खाली मान रख सकते हैं। – Tiny

+0

ठीक है, आप पूरी तरह से राज्य ('forClass = String.class' का उपयोग करके) ** ** ** प्रत्येक ** स्ट्रिंग के लिए है? तो चीजों को याद रखने की जरूरत नहीं है। हमेशा कस्टम ' ';-) – Kukeltje

उत्तर

4

पहली जगह, Converter कभी भी "डिफ़ॉल्ट मान" लागू करने का इरादा नहीं है।

सवाल है, जो कुछ भी आप getAsString() में क्या की परवाह किए बिना, आप गारंटी चाहिए कि जिसके परिणामस्वरूप String वापस मूल Object में बदला जा सकता है जब आप इसे वापस getAsObject() के माध्यम से गुजरती हैं। आपका कनवर्टर ऐसा नहीं करता है। भले ही आप इसे कभी भी उपयोग नहीं करेंगे, तकनीकी रूप से कनवर्टर को सटीक स्ट्रिंग "Not available" को null पर परिवर्तित करने के लिए संशोधित करने की आवश्यकता है।दूसरे शब्दों में, आपके कनवर्टर को इस तरह से डिजाइन किया जाना चाहिए कि getAsObject() और getAsString() एक दूसरे के परिणाम को अनंत लूप में सफलतापूर्वक पारित कर सकते हैं और हर बार एक ही परिणाम दे सकते हैं।

Converter में डिफ़ॉल्ट मान लागू करने की ठोस कार्यात्मक आवश्यकता के रूप में, आपको वास्तविक डिफ़ॉल्ट मान कहां से आ रहा है, इस पर निर्भर करते हुए आपको मॉडल या दृश्य में ऐसा करना चाहिए। आपके विशिष्ट मामले में, जब आप ऐसा कोई मान नहीं रखते हैं तो आप उपयोगकर्ता इंटरफ़ेस में डिफ़ॉल्ट प्लेसहोल्डर टेक्स्ट/लेबल रखना चाहते हैं। यह दृश्य में है।

हर जगह #{empty bean.value ? 'Not available' : bean.value} तरह ईएल में एक सशर्त परीक्षण लाना आवेदन भर पागलपन है।

मैं पूरी तरह से सहमत हूं कि यह पागलपन है यदि आप पहले ही एप्लिकेशन विकास के आधे रास्ते की तरह हैं और उनमें से सैकड़ों सभी जगहों पर हैं। हालांकि, अगर आप पहले ही शुरुआत से ही इसे ध्यान में रखते हैं तो यह पागलपन नहीं है। यदि आपने नहीं किया, तो अच्छी तरह से, सबक सीखें, बुलेट काट लें और नियमित रूप से कोड को ठीक करें। डीसेंट आईडीई में रेगेक्स आधारित & है जो इस में सहायता कर सकता है। हर कोई वहां रहा है और उस तरह की पागलपन भी किया है, यहां तक ​​कि खुद भी। बॉयलरप्लेट को कम करने के लिए, इसे ईएल फ़ंक्शन या टैगफाइल में लपेटें।

Converter लागू नहीं किया जा रहा है जब मॉडल मूल्य null है, जो मैं व्यक्तिगत रूप से पूरी तरह से अनपेक्षित व्यवहार होने के लिए सहमत का ठोस समस्या के रूप में, यह कभी Mojarra issue 630 के रूप में सूचना मिली थी। इसे बाद में WONTFIX के रूप में बंद कर दिया गया क्योंकि यह परीक्षण केस विफलताओं का कारण बनता है और जेएसएफ विनिर्देशन मुद्दे के रूप में रिपोर्ट करने के बाद बेहतर होता है। यह JSF spec issue 475 (जेएसएफ 1.2 के दौरान पहले से ही) के रूप में किया गया था। मैंने इस पर MyFaces 2.2.9 की जांच की है और यह कनवर्टर को ट्रिगर नहीं करता है और इस प्रकार एक ही स्पेस समस्या का खुलासा करता है।

तकनीकी समस्या, हालांकि, समझ में आता है। null मान में कोई समझदार getClass() नहीं है, इसलिए कनवर्टर को इस तरह के मूल्य वर्ग द्वारा देखा नहीं जा सकता है। यह तभी काम करता है जब कनवर्टर घटक पर स्पष्ट रूप से पंजीकृत होता है।

<h:outputText value="#{bean.potentiallyNullValue}" converter="stringTrimmer" /> 

जब मूल्य एक खाली स्ट्रिंग "" है, जो अपेक्षाकृत Mojarra के TextRenderer विस्तार कस्टम रेंडरर का getValue() में लागू करने के लिए तुच्छ है यह काम करना चाहिए।

@Override 
protected Object getValue(UIComponent component) { 
    Object value = super.getValue(component); 
    return (value != null) ? value : ""; 
} 

हालांकि, जब मैंने इसे स्वयं यहां करने की कोशिश की, तो यह अभी भी विफल रहा। क्या निकलता है, जब कनवर्टर-बाय-क्लास पूरी तरह से छोड़ा जाता है जब मान String का उदाहरण होता है। यह तब भी काम करता है जब कनवर्टर घटक पर स्पष्ट रूप से पंजीकृत होता है। यह जेएसएफ 1.2 के लिए spec issue 131 को लागू करने के दौरान सबसे अधिक संभावना है (इस संस्करण से पहले, String.class के लिए कन्वर्टर्स बिल्कुल समर्थित नहीं थे और इस समस्या ने इसे केवल डीकोड के लिए तय किया, न कि एन्कोड के लिए)।

यह getFormattedValue() की ओवरराइड नीचे जिससे कनवर्टर स्पष्ट रूप से देखा जाता है के साथ एक ही कस्टम रेंडरर (ऊपर getValue() ओवरराइड के साथ) में ओवरराइड किया जा सकता।

@Override 
protected String getFormattedValue(FacesContext context, UIComponent component, Object currentValue) throws ConverterException { 
    Converter converter = ((UIOutput) component).getConverter(); 

    if (converter == null) { 
     converter = context.getApplication().createConverter(currentValue.getClass()); 
    } 

    return super.getFormattedValue(context, component, "".equals(currentValue) ? null : currentValue, converter); 
} 

ध्यान दें कि आप UIInput के लिए जाँच करने के रूप में आप स्पष्ट रूप पर javax.faces.Output/javax.faces.Text घटक परिवार/प्रकार अपने कस्टम रेंडरर पंजीकृत कर लिया है केवल (यानी यह केवल <h:outputText> घटकों पर चलेगा) की जरूरत नहीं है।

फिर भी, इसके लिए सबसे अच्छा समाधान अभी भी एक ईएल फ़ंक्शन या टैगफाइल बनाना है।

<h:outputText value="#{empty bean.value ? 'Not available' : bean.value}" /> 
<h:outputText value="#{of:coalesce(bean.value, 'Not Available')}" /> 
<h:outputText value="#{of:coalesce(bean.value, i18n.na)}" /> 
<h:outputText value="#{your:value(bean.value)}" /> 
<your:text value="#{bean.value}" /> 
+0

'getVormattedValue()' के अंदर 'currentValue' का मान किसी भी समय' शून्य 'हो सकता है। इसलिए, 'currentValue.getClass() 'रेंडरर में' java.lang.NullPointerException' फेंक देगा, अगर' currentValue' 'null' है। – Tiny

+0

यदि आप 'getValue()' को ओवरराइड नहीं करते हैं। मैं शायद पर्याप्त स्पष्ट नहीं था, मैंने जवाब स्पष्ट किया। – BalusC

+0

किसी अन्य प्रकार के कनवर्टर में एक और परिणाम है। मेरे पास [पिछले प्रश्न] (http://stackoverflow.com/q/35347001/1391249) के रूप में एक 'BigDecimal' कनवर्टर है)। यदि डेटाबेस में 'BigDecimal' प्रकार का मान 'शून्य' है, तो 'getAsString()' में पुनर्प्राप्त 'मॉडल वैल्यू' एक खाली स्ट्रिंग है - 'System.out.println (" modelValue: "+ ((स्ट्रिंग) मॉडल वैल्यू)। isEmpty()); 'getAsString()' में 'सत्य 'देता है। यह 'getAsString()' विधि के अंदर 'if-else-if-else' सीढ़ी 'में निर्दिष्ट के रूप में' नया कनवर्टर अपवाद ("संदेश") तक पहुंचता है। ('मॉडल वैल्यू' को वहां 'शून्य' होने की उम्मीद है, अगर यह डीबी में 'शून्य' है) – Tiny