2014-06-23 5 views
5

नहीं चाहता "यह प्रश्न" वैचारिक "या" मैं जेएसएफ नहीं समझता "प्रकार का अधिक हो सकता हूं।सेट ऑपरेशन के लिए अवैध सिंटेक्स: जेएसएफ को कैसे बताना है मैं एक सेटर

मेरे परिदृश्य: मैं एक JSF पृष्ठ (index.xhtml) मैं कहाँ का प्रयोग कर एक p:accordionPanel (लेकिन मैं यह मायने रखती है नहीं लगता कि क्या घटक यह है है)। मैं क्या करना चाहता हूं activeIndexes इसे सेट करना है।

<p:accordionPanel multiple="true" activeIndex="#{myController.getActiveIndexesForSections('whatever')}"> 
// bla bla... 
</p:accordionPanel> 

और (सरलीकृत) समर्थन की फलियों में विधि:

public String getActiveIndexesForSections(String holderName){ 
    String activeSections = ""; 
    for(Section s : sectionMap.get(holderName)){ 
     if (s.isActive()) 
     //add to the string 
    } 
    return activeSections; 
} 

अब यह एक सामान्य पृष्ठ लोड पर बस ठीक काम करता है।

लेकिन अगर मैं पर एक p:commandButton (ajax=false के साथ) क्लिक करें (या जो कुछ और डेटा वापस "भेजता है" सर्वर मुझे लगता है कि करने के लिए) - मैं निम्न अपवाद प्राप्त करें:

/WEB-INF/tags/normalTextSection.xhtml @8,112 activeIndex="#{myController.getActiveIndexesForSections(name)}": Illegal Syntax for Set Operation 
// bla.. 
Caused by: javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation 

कुछ Googling/पढ़ने के बाद त्रुटि संदेश मैंने पाया कि मुझे setter की आवश्यकता है।

सबसे पहले: मुझे एक सेटटर नहीं चाहिए - क्या मुझे वास्तव में एक की आवश्यकता है या जेएसएफ को बताने का कोई तरीका है, मैं यह "व्यवहार" नहीं चाहता हूं।

सेकेंड मुझे एहसास हुआ कि यह एक सेटटर प्रदान करने के लिए "आसान" नहीं है, क्योंकि मेरी विधि में पैरामीटर है (इसलिए public void setActiveIndexesForSections(String name, String activeIndexes) या public void setActiveIndexesForSections(String name) काम नहीं करेगा)। क्या मैं अंत में के साथ आया है:

एक (सामान्य) "छद्म संपत्ति श्रेणी" बनाएँ:

// just a dummy class since the class is recreated at every request 
public class Property<T> implements Serializable { 

    private T val; 

    public Property(T val) { 
     this.val= val; 
    } 

    public T getVal() { 
     return val; 
    } 

      //no need to do anyhting 
    public void setVal(T val) { 
    } 
} 

बदलें सेम विधि:

public Property<String> getActiveIndexesForSections(String holderName){ 
    String activeSections = ""; 
    for(Section s : sectionMap.get(holderName)){ 
     if (s.isActive()) 
     //add to the string 
    } 
    return new Property<String>(activeSections); 
} 

और यह फोन index.xhtml से:

<p:accordionPanel multiple="true" activeIndex="#{myController.getActiveIndexesForSections('whatever').val}"> 
// bla bla... 
</p:accordionPanel> 

यह काम करता है लेकिन स्पष्ट रूप से एक बदसूरत हैक है/wo rkaround।

इस तरह की स्थिति को संभालने का उचित तरीका क्या है? या क्या मैं बस पूरी तरह से गलत कर रहा हूँ?

उत्तर

17

सक्रिय इंडेक्स को याद रखने के लिए सेटटर की आवश्यकता होती है जब फॉर्म सबमिट किया गया था। असल में, आपको इसे एक मूल्य अभिव्यक्ति (एक संपत्ति के साथ) के रूप में बाध्य करने की आवश्यकता है, विधि विधि (जैसे एक क्रिया विधि) के रूप में नहीं, न ही एक अप्रत्याशित संग्रह (जैसे activeIndex="#{param.tab}")। बिल्कुल इनपुट मानों की तरह ही। तकनीकी रूप से, आप वास्तव में इसे "पूरी तरह से गलत" कर रहे हैं;)

आवश्यकता को समझ लिया गया है। यह देखते हुए कि आप वास्तव में परिवर्तित सक्रिय इंडेक्स में रूचि नहीं रखते हैं, और इस प्रकार उन्हें सबमिट किए गए प्रत्येक फॉर्म पर डिफ़ॉल्ट पर रीसेट करना चाहते हैं, तो आप परिणाम को <c:set> की सहायता से अनुरोध विशेषता के रूप में संग्रहीत करके बाईपास कर सकते हैं। इस तरह आप ईएल को मूर्खतापूर्ण बीन संपत्ति के बजाय अनुरोध विशेषता मानचित्र में सेट करने के लिए मूर्ख बना देंगे।

<c:set var="activeIndex" value="#{myController.getActiveIndexesForSections('whatever')}" scope="request" /> 
<p:accordionPanel multiple="true" activeIndex="#{activeIndex}"> 
    <!-- bla bla... --> 
</p:accordionPanel> 

कवर के तहत, यह मूल रूप से सेटर ऑपरेशन है, जो स्पष्ट रूप से बस के रूप में काम करेंगे externalContext.getRequestMap().put("activeIndex", value) करेंगे।


अद्यतन: source code of AccordionPanel component निरीक्षण पर, मैं इस तथ्य जब rendered विशेषता का मूल्यांकन करता है falseactiveIndex सेट नहीं किया जाएगा कि दिए गए एक और वैकल्पिक हल देखा। तो बस rendered विशेषता को वास्तव में व्यवहार करने के लिए बदलें: अद्यतन मॉडल मूल्य चरण (चौथा चरण) के दौरान false का मूल्यांकन करें।

<p:accordionPanel multiple="true" 
    activeIndex="#{myController.getActiveIndexesForSections('whatever')}" 
    rendered="#{facesContext.currentPhaseId.ordinal ne 4}"> 
    <!-- bla bla... --> 
</p:accordionPanel> 
+0

मुझ पर दया करने के लिए धन्यवाद;) क्या आप इसे करने का एक और तरीका सुझाएंगे - क्योंकि यह "बस" गलत है? (जो मैं विश्वास नहीं कर सकता, यह है कि यह उपयोग मामला इतना दुर्लभ है कि कोई भी (मुझे उम्मीद नहीं करता) कभी ऐसा करना चाहता था - इसलिए मैं वास्तव में सोच रहा हूं कि क्या मैं बड़ी तस्वीर को याद करता हूं ...) - इसके अलावा मेरा 'accordionPanel' एक टैग के भीतर जेनरेट किया जाता है जहां 'जो भी' पैरामीटर के रूप में पारित किया जाता है - क्या मैं पैरामीटर का उपयोग 'c: set'' के रूप में भी कर सकता हूं और फिर 'accordionPanel' के' सक्रिय इंडेक्स 'के रूप में कर सकता हूं? यदि हां, तो कैसे? –

+1

इस विशिष्ट मामले में सही तरीका कस्टम 'मानचित्र' कार्यान्वयन वापस कर देगा। और नहीं, आप 'var' विशेषता में ईएल का उपयोग नहीं कर सकते हैं, इसलिए एक टैगफाइल खराब होगा। किसी भी तरह से, '' के स्रोत कोड का निरीक्षण करने के बाद, मैंने एक और कामकाज देखा जो टैगफाइल में बेहतर पुन: प्रयोज्य है। उत्तर अपडेट देखें। – BalusC

+0

धन्यवाद। कल और 'कस्टम' 'मानचित्र' भी कोशिश करेंगे। और यदि यह काम करता है + "बक्षीस" आप स्वीकार करते हैं :) –

संबंधित मुद्दे