मैं चयनित पंक्ति को डेटाटेबल या यूआई के अंदर कमांड करने के लिए कैसे पास कर सकता हूं: दोहराएं?


99

मैं JSF 2 एप्लिकेशन में प्रधानमंत्री का उपयोग कर रहा हूं। मेरे पास एक है <p:dataTable>, और पंक्तियों का चयन करने के बजाय, मैं चाहता हूं कि उपयोगकर्ता व्यक्तिगत पंक्तियों पर विभिन्न कार्यों को सीधे निष्पादित करने में सक्षम हो। उसके लिए, मेरे पास <p:commandLink>पिछले कॉलम में कई s हैं।

मेरी समस्या: मैं कमांड लिंक द्वारा शुरू की गई कार्रवाई के लिए एक पंक्ति आईडी कैसे पास कर सकता हूं ताकि मुझे पता हो कि किस पंक्ति पर कार्य करना है? मैंने एक का उपयोग करने की कोशिश की <f:attribute>:

<p:dataTable value="#{bean.items}" var="item">
    ...
    <p:column>
        <p:commandLink actionListener="#{bean.insert}" value="insert">
            <f:attribute name="id" value="#{item.id}" />
        </p:commandLink>
    </p:column>
</p:dataTable>

लेकिन यह हमेशा 0 देता है - जाहिर है कि पंक्ति चर fउपलब्ध नहीं है जब विशेषता प्रदान की जाती है (यह तब काम करता है जब मैं एक निश्चित मूल्य का उपयोग करता हूं)।

किसी के पास कोई वैकल्पिक उपाय है?

जवाबों:


215

कारण के रूप में, <f:attribute> रूप में, घटक के लिए विशिष्ट है (व्यू बिल्ड समय के दौरान आबादी), पुनरावृत्त पंक्ति पर नहीं (दृश्य रेंडर समय के दौरान आबादी)।

आवश्यकता को प्राप्त करने के कई तरीके हैं।

  1. यदि आपका सर्वलेटेनर न्यूनतम सर्वलेट 3.0 / ईएल 2.2 का समर्थन करता है, तो बस इसे UICommand घटक या AjaxBehaviorटैग की कार्रवाई / श्रोता विधि के तर्क के रूप में पास करें । उदाहरण के लिए

     <h:commandLink action="#{bean.insert(item.id)}" value="insert" />

    के साथ सम्मिलन में:

     public void insert(Long id) {
         // ...
     }

    इसके लिए केवल यह आवश्यक है कि फॉर्म सबमिट अनुरोध के लिए डेटामॉडल संरक्षित है। सबसे अच्छा यह है कि सेम को व्यू स्कोप के दायरे में रखा जाए@ViewScoped

    तुम भी पूरे आइटम वस्तु पारित कर सकते हैं:

     <h:commandLink action="#{bean.insert(item)}" value="insert" />

    साथ में:

     public void insert(Item item) {
         // ...
     }

    सर्वलेट 2.5 कंटेनरों पर, यह भी संभव है यदि आप एक ईएल कार्यान्वयन की आपूर्ति करते हैं जो इस तरह का समर्थन करता है, जैसे कि JBoss EL। कॉन्फ़िगरेशन विवरण के लिए, यह उत्तर देखें ।


  2. घटक <f:param>में उपयोग करें UICommand। यह एक अनुरोध पैरामीटर जोड़ता है।

     <h:commandLink action="#{bean.insert}" value="insert">
         <f:param name="id" value="#{item.id}" />
     </h:commandLink>

    यदि आपकी सेम अनुरोधित है, तो JSF इसे सेट करें @ManagedProperty

     @ManagedProperty(value="#{param.id}")
     private Long id; // +setter

    या यदि आपके बीन का व्यापक दायरा है या आप अधिक महीन दाने वाली मान्यता / रूपांतरण चाहते हैं, <f:viewParam>तो लक्ष्य दृश्य पर उपयोग करें , यह भी देखें f: viewParam बनाम @ManagedProperty :

     <f:viewParam name="id" value="#{bean.id}" required="true" />

    किसी भी तरह से, इसका यह फायदा है कि डेटामोडेल को फॉर्म सबमिट करने के लिए जरूरी नहीं है (इस मामले के लिए कि आपका बीन अनुरोधित है)।


  3. घटक <f:setPropertyActionListener>में उपयोग करें UICommand। लाभ यह है कि यह अनुरोध पैरामीटर मानचित्र तक पहुंचने की आवश्यकता को हटा देता है जब बीन में अनुरोध क्षेत्र की तुलना में व्यापक गुंजाइश होती है।

     <h:commandLink action="#{bean.insert}" value="insert">
         <f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" />
     </h:commandLink>

    के साथ सम्मिलन में

     private Long id; // +setter

    यह सिर्फ idएक्शन विधि में संपत्ति द्वारा उपलब्ध होगा । इसके लिए केवल यह आवश्यक है कि फॉर्म जमा अनुरोध के लिए डेटामॉडल संरक्षित है। सबसे अच्छा यह है कि सेम को व्यू स्कोप में रखा जाए @ViewScoped


  4. DataModel<E>इसके बजाए डेटेबल मूल्य को बांधें जो बदले में वस्तुओं को लपेटता है।

     <h:dataTable value="#{bean.model}" var="item">

    साथ में

     private transient DataModel<Item> model;
    
     public DataModel<Item> getModel() {
         if (model == null) {
             model = new ListDataModel<Item>(items);
         }
         return model;
     }

    (इसे बनाने transientऔर आलसी में इसे तुरंत बनाना अनिवार्य है, जब आप इसे किसी दृश्य या सत्र में उपयोग कर रहे हैं, जो सेम को DataModelलागू नहीं करता हैSerializable )

    तब आप वर्तमान पंक्ति के DataModel#getRowData()चारों ओर कुछ भी पास किए बिना पहुंच सकेंगे (JSF क्लिक कमांड लिंक / बटन के अनुरोध पैरामीटर नाम के आधार पर पंक्ति निर्धारित करता है)।

     public void insert() {
         Item item = model.getRowData();
         Long id = item.getId();
         // ...
     }

    इसके लिए यह भी आवश्यक है कि फॉर्म जमा अनुरोध के लिए डेटामॉडल संरक्षित है। सबसे अच्छा यह है कि सेम को व्यू स्कोप में रखा जाए @ViewScoped


  5. Application#evaluateExpressionGet()प्रोग्राम का वर्तमान में मूल्यांकन करने के लिए उपयोग करें #{item}

     public void insert() {
         FacesContext context = FacesContext.getCurrentInstance();
         Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class);
         Long id = item.getId();
         // ...
     }

चुनने का कौन सा तरीका कार्यात्मक आवश्यकताओं पर निर्भर करता है और क्या एक या दूसरे अन्य प्रयोजनों के लिए अधिक लाभ प्रदान करता है। मैं व्यक्तिगत रूप से # 1 के साथ आगे बढ़ूंगा, या जब आप सर्वलेट 2.5 कंटेनरों के साथ # 2 का समर्थन करना चाहेंगे।


1
+1, हालाँकि मेरी प्राथमिकता # 2 पर जाती है (यदि 2.5 का समर्थन किया जाना है)।
17

संपूर्ण उत्तर के लिए धन्यवाद। दुर्भाग्य से, मुझे यह रिपोर्ट करना है कि # 1 एकमात्र ऐसी चीज़ थी जो फ़िल्टर किए गए प्रधान स्थानों में काम करने योग्य थी (जो कि वास्तव में मेरे लिए आवश्यक है)। अन्य सभी ने केवल एक अनफ़िल्टर्ड टेबल पर काम किया। मैं इसे आपके उत्तर की तुलना में प्राइमफेस में बग के रूप में अधिक देखता हूं, हालांकि।
माइकल बॉर्गवर्ड

क्या बीन का अनुरोध या देखने से बदनामी हुई है?
BalusC

2
"फ़िल्टर्ड" के साथ इस शोकेस उदाहरण में आपका मतलब है ? लक्षणों से संकेत मिलता है कि फ़िल्टर कार्रवाई क्लाइंट साइड में ही होती है और सर्वर साइड में मॉडल को बनाए नहीं रखा जाता है। यकीन नहीं होता कि यह जानबूझकर है। आप हमेशा एक समस्या रिपोर्ट छोड़ सकते हैं।
बालूसाक

आपकी पोस्ट मेरे द्वारा पढ़े गए सबसे उपयोगी पोस्ट के बीच है। मैंने पद्धति 5 का उपयोग किया क्योंकि मैं सर्वलेट 2.5 का उपयोग करने के लिए मजबूर हूं। मेरा सवाल अब यह है कि क्या कमांडलिंक के साथ एक पैरामीटर भेजना संभव है (जैसे आपके उदाहरण में), लेकिन अजाक्स का उपयोग करना?
एडिट्ज़ू

11

JSF 1.2 में यह <f:setPropertyActionListener>(कमांड कंपोनेंट के भीतर) किया गया था । JSF 2.0 (EL 2.2 सटीक होने के लिए, BalusC के लिए धन्यवाद) इसे इस तरह से करना संभव है:action="${filterList.insert(f.id)}


6
यह सुविधा JSF 2.0 (जो कि सर्वलेट 2.5 कंटेनरों में स्वयं चल सकती है) के लिए विशिष्ट नहीं है, लेकिन EL 2.2 (जो सर्वलेट 3.0 का हिस्सा है) के लिए।
बालुस

11

मेरे विचार पृष्ठ में:

<p:dataTable  ...>
<p:column>
<p:commandLink actionListener="#{inquirySOController.viewDetail}" 
               process="@this" update=":mainform:dialog_content"
           oncomplete="dlg2.show()">
    <h:graphicImage library="images" name="view.png"/>
    <f:param name="trxNo" value="#{item.map['trxNo']}"/>
</p:commandLink>
</p:column>
</p:dataTable>

बैकिंग बीन

 public void viewDetail(ActionEvent e) {

    String trxNo = getFacesContext().getRequestParameterMap().get("trxNo");

    for (DTO item : list) {
        if (item.get("trxNo").toString().equals(trxNo)) {
            System.out.println(trxNo);
            setSelectedItem(item);
            break;
        }
    }
}

-1

मिकॉन्ग द्वारा इस साइट के लिए धन्यवाद , एकमात्र समाधान जो वास्तव में हमारे लिए एक पैरामीटर पास करने के लिए काम करता था, यह था

<h:commandLink action="#{user.editAction}">
    <f:param name="myId" value="#{param.id}" />
</h:commandLink>

साथ में

public String editAction() {

  Map<String,String> params = 
            FacesContext.getExternalContext().getRequestParameterMap();
  String idString = params.get("myId");
  long id = Long.parseLong(idString);
  ...
}

तकनीकी रूप से, आप सीधे ही विधि को पारित नहीं कर सकते, लेकिन JSF request parameter map


1
आपने यहां पूछा एक अलग समस्या है। आप #{param}बाद के अनुरोधों के लिए मानचित्र से अनुरोध मापदंडों को बनाए रखना चाहते हैं, न कि एक मनमाना पैरामीटर पारित करना। आपके प्रश्न और उत्तर से आच्छादित है stackoverflow.com/questions/17734230
BalusC
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.