Ajax अपडेट / रेंडर के लिए घटक की क्लाइंट आईडी कैसे पता करें? "बार" से संदर्भित "फू" अभिव्यक्ति के साथ घटक नहीं मिल सकता


140

निम्न कोड प्राइमफेस डेटाग्रेड + डेटाटेबल ट्यूटोरियल्स से प्रेरित है और एक <p:tab>के एक में <p:tabView>रहने वाले में रखा गया <p:layoutUnit>है <p:layout>। यहां कोड का आंतरिक भाग ( p:tabघटक से शुरू ) है; बाहरी हिस्सा तुच्छ है।

<p:tabView id="tabs">
    <p:tab id="search" title="Search">                        
        <h:form id="insTable">
            <p:dataTable id="table" var="lndInstrument" value="#{instrumentBean.instruments}">
                <p:column>
                    <p:commandLink id="select" update="insTable:display" oncomplete="dlg.show()">
                        <f:setPropertyActionListener value="#{lndInstrument}" 
                                        target="#{instrumentBean.selectedInstrument}" />
                        <h:outputText value="#{lndInstrument.name}" />
                    </p:commandLink>                                    
                </p:column>
            </p:dataTable>
            <p:dialog id="dlg" modal="true" widgetVar="dlg">
                <h:panelGrid id="display">
                    <h:outputText value="Name:" />
                    <h:outputText value="#{instrumentBean.selectedInstrument.name}" />
                </h:panelGrid>
            </p:dialog>                            
        </h:form>
    </p:tab>
</p:tabView>

जब मैं क्लिक करता हूं <p:commandLink>, तो कोड काम करना बंद कर देता है और संदेश देता है:

अभिव्यक्ति "असंवेदनशील: प्रदर्शन" के साथ घटक नहीं मिल सकता है "टैब से संदर्भित: असंवेदनशील: चुनें"।

जब मैं उसी का उपयोग करने की कोशिश करता हूं <f:ajax>, तो यह मूल रूप से एक ही बता रहे एक अलग संदेश के साथ विफल हो जाता है:

<f:ajax> एक अज्ञात आईडी शामिल है "insTable: display" इसे घटक "टैब: insTable: select" के संदर्भ में ढूँढ नहीं सकता है

यह कैसे होता है और मैं इसे कैसे हल कर सकता हूं?

जवाबों:


313

वास्तविक ग्राहक आईडी के लिए HTML आउटपुट में देखें

आपको सही क्लाइंट आईडी का पता लगाने के लिए उत्पन्न HTML आउटपुट में देखना होगा। ब्राउज़र में पेज खोलें, एक राइटक्लिक करें और सोर्स देखें । जेएसएफ घटक के एचटीएमएल प्रतिनिधित्व का पता लगाएँ और इसे idग्राहक आईडी के रूप में लें । आप इसे वर्तमान नामकरण कंटेनर के आधार पर निरपेक्ष या सापेक्ष तरीके से उपयोग कर सकते हैं। निम्नलिखित अध्याय देखें।

नोट: यदि ऐसा होता है कि पुनरावृत्ति सूचकांक जैसे :0:, :1:आदि (क्योंकि यह एक पुनरावृत्ति घटक के अंदर है), तो आपको यह महसूस करने की आवश्यकता है कि एक विशिष्ट पुनरावृत्ति गोल को अपडेट करना हमेशा समर्थित नहीं होता है। उस पर और अधिक विस्तार के लिए जवाब के नीचे देखें।

NamingContainerघटकों को याद रखें और हमेशा उन्हें एक निश्चित आईडी दें

यदि कोई घटक जिसे आप अजाक्स प्रक्रिया द्वारा संदर्भित करना चाहते हैं / निष्पादित / अपडेट / प्रस्तुत करना उसी NamingContainerमाता-पिता के अंदर है , तो बस अपनी आईडी का संदर्भ दें।

<h:form id="form">
    <p:commandLink update="result"> <!-- OK! -->
    <h:panelGroup id="result" />
</h:form>

यदि यह उसी के अंदर नहीं है NamingContainer, तो आपको एक निरपेक्ष ग्राहक आईडी का उपयोग करके इसे संदर्भित करना होगा। एक निरपेक्ष क्लाइंट आईडी NamingContainerविभाजक चरित्र के साथ शुरू होता है , जो डिफ़ॉल्ट रूप से होता है :

<h:form id="form">
    <p:commandLink update="result"> <!-- FAIL! -->
</h:form>
<h:panelGroup id="result" />
<h:form id="form">
    <p:commandLink update=":result"> <!-- OK! -->
</h:form>
<h:panelGroup id="result" />
<h:form id="form">
    <p:commandLink update=":result"> <!-- FAIL! -->
</h:form>
<h:form id="otherform">
    <h:panelGroup id="result" />
</h:form>
<h:form id="form">
    <p:commandLink update=":otherform:result"> <!-- OK! -->
</h:form>
<h:form id="otherform">
    <h:panelGroup id="result" />
</h:form>

NamingContainerघटकों, उदाहरण के लिए कर रहे हैं <h:form>, <h:dataTable>, <p:tabView>, <cc:implementation>(इस प्रकार, सभी समग्र घटकों), आदि आप उन्हें आसानी से उत्पन्न HTML आउटपुट को देखकर पहचान, उनके आईडी सभी बच्चे घटकों के उत्पन्न ग्राहक आईडी के लिए prepended किया जाएगा। ध्यान दें कि जब उनके पास एक निश्चित आईडी नहीं है, तो JSF j_idXXXप्रारूप में एक ऑटोजेनरेटेड आईडी का उपयोग करेगा । आपको निश्चित आईडी देकर उन्हें इससे बचना चाहिए। OmniFacesNoAutoGeneratedIdViewHandler विकास के दौरान यह करने में सहायक हो सकता है।

यदि आप UIComponentप्रश्न में जेवाडॉक को ढूंढना जानते हैं , तो आप बस वहां भी जांच कर सकते हैं कि यह NamingContainerइंटरफ़ेस को लागू करता है या नहीं। उदाहरण के लिए, HtmlForm( UIComponentपीछे <h:form>टैग) इसे लागू दिखाता है NamingContainer, लेकिन HtmlPanelGroup( UIComponentपीछे <h:panelGroup>टैग) यह नहीं दिखाता है, इसलिए यह लागू नहीं होता है NamingContainerयहाँ सभी मानक घटकों का javadoc है और यहाँ PrimeFaces का javadoc है

आपकी समस्या का समाधान

तो आपके मामले में:

<p:tabView id="tabs"><!-- This is a NamingContainer -->
    <p:tab id="search"><!-- This is NOT a NamingContainer -->
        <h:form id="insTable"><!-- This is a NamingContainer -->
            <p:dialog id="dlg"><!-- This is NOT a NamingContainer -->
                <h:panelGrid id="display">

उत्पन्न HTML उत्पादन <h:panelGrid id="display">इस तरह दिखता है:

<table id="tabs:insTable:display">

आपको idग्राहक आईडी के रूप में ठीक वैसा ही लेना होगा और फिर :उपयोग के लिए उपसर्ग update:

<p:commandLink update=":tabs:insTable:display">

बाहर संदर्भित में शामिल हैं / टैगफाइल / समग्र

यदि यह कमांड लिंक किसी सम्‍मिलित / टैगफाइल के अंदर है, और लक्ष्‍य इसके बाहर है, और इस प्रकार आपको वर्तमान नामकरण कंटेनर के नामकरण कंटेनर माता-पिता की आईडी नहीं पता है, तो आप इसे गतिशील रूप से इस UIComponent#getNamingContainer()तरह से संदर्भित कर सकते हैं :

<p:commandLink update=":#{component.namingContainer.parent.namingContainer.clientId}:display">

या, यदि यह कमांड लिंक एक मिश्रित घटक के अंदर है और लक्ष्य इसके बाहर है:

<p:commandLink update=":#{cc.parent.namingContainer.clientId}:display">

या, यदि कमांड लिंक और लक्ष्य दोनों एक ही मिश्रित घटक के अंदर हैं:

<p:commandLink update=":#{cc.clientId}:display">

प्रस्तुतिकरण / अद्यतन विशेषता के लिए टेम्पलेट में मूल नामकरण कंटेनर की आईडी भी देखें

यह कवर के तहत कैसे काम करता है

यह सब जावास्क्रिप्ट में "खोज अभिव्यक्ति" के रूप में निर्दिष्ट किया गया हैUIComponent#findComponent() :

एक खोज अभिव्यक्ति में या तो एक पहचानकर्ता होता है (जिसका मिलान आईडी प्रॉपर्टी के बिलकुल विपरीत होता है UIComponent, या UINamingContainer#getSeparatorCharचरित्र मान से जुड़े ऐसे पहचानकर्ताओं की एक श्रृंखला होती है । खोज एल्गोरिथम इस प्रकार संचालित होता है, हालांकि वैकल्पिक अलोग्रिथम का उपयोग तब तक किया जा सकता है। अंतिम परिणाम समान है:

  • UIComponentनिम्न में से किसी एक स्थिति के पूरा होते ही, खोज के लिए आधार की पहचान करें :
    • यदि खोज अभिव्यक्ति विभाजक चरित्र (जिसे "पूर्ण" खोज अभिव्यक्ति कहा जाता है) से शुरू होता है, तो आधार UIComponentघटक पेड़ की जड़ होगा । अग्रणी विभाजक चरित्र को हटा दिया जाएगा, और शेष खोज अभिव्यक्ति को "रिश्तेदार" खोज अभिव्यक्ति के रूप में नीचे वर्णित किया जाएगा।
    • अन्यथा, यदि यह UIComponentहै तो यह NamingContainerआधार के रूप में काम करेगा।
    • अन्यथा, इस घटक के माता-पिता को खोजें। यदि एक NamingContainerका सामना किया जाता है, तो यह आधार होगा।
    • अन्यथा (यदि कोई NamingContainerसामना नहीं हुआ है) मूल UIComponentआधार होगा।
  • खोज अभिव्यक्ति (संभवतः पिछले चरण में संशोधित) अब एक "सापेक्ष" खोज अभिव्यक्ति है जिसका उपयोग आधार घटक के दायरे के भीतर मेल खाने वाले घटक (यदि कोई है) से मेल खाने के लिए किया जाएगा। मैच निम्नानुसार किया जाता है:
    • यदि खोज अभिव्यक्ति एक साधारण पहचानकर्ता है, तो यह मान आईडी प्रॉपर्टी की तुलना में है, और फिर आधार के पहलुओं और बच्चों के माध्यम से पुनरावृत्ति करता है UIComponent(सिवाय इसके कि अगर कोई वंशज NamingContainerपाया जाता है, तो उसके स्वयं के पहलुओं और बच्चों की खोज नहीं की जाती है)।
    • यदि खोज अभिव्यक्ति में विभाजक वर्ण द्वारा अलग किए गए एक से अधिक पहचानकर्ता शामिल हैं, तो पहले पहचानकर्ता का उपयोग NamingContainerपिछले बुलेट बिंदु में नियमों द्वारा पता लगाने के लिए किया जाता है। फिर, खोज अभिव्यक्ति के शेष भाग को पारित findComponent()करने के लिए इस पद्धति को NamingContainerबुलाया जाएगा।

ध्यान दें कि PrimeFaces JSF कल्पना का भी पालन करता है, लेकिन RichFaces "कुछ अतिरिक्त अपवादों" का उपयोग करता है ।

"reRender"UIComponent.findComponent() घटक पेड़ में घटक को खोजने के लिए एल्गोरिथ्म (कुछ अतिरिक्त अपवादों के साथ) का उपयोग करता है।

उन अतिरिक्त अपवादों का कहीं भी विस्तार से वर्णन नहीं किया गया है, लेकिन यह ज्ञात है कि रिश्तेदार घटक आईडी (यानी जिनके साथ शुरू :नहीं होते हैं) न केवल निकटतम माता-पिता के संदर्भ में खोजे जाते हैं NamingContainer, बल्कि NamingContainerएक ही दृश्य में अन्य सभी घटकों में भी (जो अपेक्षाकृत है) महंगी नौकरी)।

कभी उपयोग न करो prependId="false"

यदि यह सब अभी भी काम नहीं करता है, तो सत्यापित करें कि आप उपयोग नहीं कर रहे हैं <h:form prependId="false">। यह ajax सबमिट और रेंडर करने की प्रक्रिया के दौरान विफल हो जाएगा। इस संबंधित प्रश्न को भी देखें: PrependId के साथ UIForm = "झूठा" टूटता है <f: ajax रेंडर>

पुनरावृत्त घटकों के विशिष्ट पुनरावृत्ति दौर को संदर्भित करना

यह लंबे समय तक संभव था कि पुनरावृत्त घटकों में एक विशिष्ट पुनरावृत्त वस्तु को संदर्भित करना संभव न हो जैसे <ui:repeat>और <h:dataTable>:

<h:form id="form">
    <ui:repeat id="list" value="#{['one','two','three']}" var="item">
        <h:outputText id="item" value="#{item}" /><br/>
    </ui:repeat>

    <h:commandButton value="Update second item">
        <f:ajax render=":form:list:1:item" />
    </h:commandButton>
</h:form>

हालाँकि, मोआजरा 2.2.5 <f:ajax>ने इसका समर्थन करना शुरू कर दिया (यह बस इसे मान्य करना बंद कर दिया; इस प्रकार अब आप कभी भी उल्लिखित अपवाद का सामना नहीं करेंगे, बाद में इसके लिए एक और वृद्धि तय की गई है)।

यह केवल वर्तमान MyFaces 2.2.7 और PrimeFaces 5.2 संस्करणों में अभी तक काम नहीं करता है। समर्थन भविष्य के संस्करणों में आ सकता है। इस बीच, आपका सबसे अच्छा शर्त यह है कि आप पुनरावृत्त घटक को अपडेट करें, या माता-पिता के मामले में यह HTML को प्रस्तुत नहीं करता है, जैसे <ui:repeat>

प्राइमफेस का उपयोग करते समय, खोज अभिव्यक्तियों या चयनकर्ताओं पर विचार करें

प्राइमफेस सर्च सर्च एक्सप्रेशन आपको जेएसएफ कंपोनेंट ट्री सर्च एक्सप्रेशन के जरिए कंपोनेंट्स को रेफर करने की सुविधा देता है। JSF में कई बिलियन हैं:

  • @this: वर्तमान घटक
  • @form: जनक UIForm
  • @all: संपूर्ण दस्तावेज
  • @none: कुछ भी तो नहीं

प्राइमफेस ने इसे नए कीवर्ड और समग्र अभिव्यक्ति समर्थन के साथ बढ़ाया है:

  • @parent: मूल घटक
  • @namingcontainer: जनक UINamingContainer
  • @widgetVar(name): घटक द्वारा दी गई पहचान के अनुसार widgetVar

तुम भी इस तरह के रूप में मिश्रित भाव में उन खोजशब्दों मिश्रण कर सकते हैं @form:@parent, @this:@parent:@parentआदि

PrimeFaces Selectors (PFS) जैसा @(.someclass)कि आप jQuery CSS चयनकर्ता वाक्यविन्यास के माध्यम से घटकों को संदर्भित करने की अनुमति देता है। उदाहरण के लिए HTML आउटपुट में सभी सामान्य शैली वर्ग वाले घटक संदर्भित होते हैं। यह विशेष रूप से उस स्थिति में सहायक है जब आपको "बहुत सारे" घटकों को संदर्भित करने की आवश्यकता होती है। यह केवल यह बताता है कि लक्षित घटकों में HTML आउटपुट में सभी क्लाइंट आईडी हैं (निश्चित या स्वतः पूर्ण, कोई फर्क नहीं पड़ता)। यह भी देखें कि अपडेट के रूप में प्रधानमंत्री चयनकर्ता कैसे हैं = "@ (। MyClass)" काम?


@jack: बस javadoc पढ़ें: docs.oracle.com/javaee/6/api/javax/faces/component/… JSF 2.0 के बाद से यह कॉन्स्टेबल के बजाय कंफर्टेबल हो गया है।
बालूसक

SEPARATOR_CHAR को पदावनत नहीं किया गया है? क्या आप नेस्टेड घटक को कॉल करने के तरीके पर एक उदाहरण दे सकते हैं, उदाहरण के लिए: context.getViewRoot().findComponent(":inputform" + UINamingContainer.getSeparatorChar(context) + "inputtext" );कृपया xHTML कोड भी शामिल करें।
जैकट्रैड्स

1
शुक्रिया, prependId="false"मेरे दिन को बचाने के साथ फॉर्म के अंदर अजाक्स रेंडर को विफल करने के बारे में ध्यान दें ।
गैम

आपके स्पष्टीकरण में उल्लिखित ग्राहक आईडी का सही अर्थ क्या है ? क्या यह JSF -> "इस घटक के लिए क्लाइंट-साइड पहचानकर्ता" के समान है। सादर + आपके काम के लिए धन्यवाद।
स्टीव ओह

1
@ antonu17: जैसा कि उत्तर में कहा गया है, यह केवल मोआजरा के f: ajax में समर्थित है।
BalusC

9

सबसे पहले: जहां तक ​​मुझे पता है कि एक टैबूव्यू के अंदर डायलॉग रखना एक बुरा अभ्यास है ... आप इसे बेहतर तरीके से निकालते हैं ...

और अब आपके प्रश्न के लिए:

क्षमा करें, मुझे कुछ समय लगा कि आप वास्तव में क्या लागू करना चाहते थे,

मेरे वेब ऐप पर अभी खुद किया है, और यह काम करता है

जैसा कि मैंने पहले कहा था पी: डायल आउट साइड 'पी: टैब व्यू,

पी छोड़ें: संवाद जैसा कि आपने शुरू में सुझाव दिया था:

<p:dialog modal="true" widgetVar="dlg">
    <h:panelGrid id="display">
        <h:outputText value="Name:" />
        <h:outputText value="#{instrumentBean.selectedInstrument.name}" />
    </h:panelGrid>
</p:dialog>   

और पी: कमांडलिंक को इस तरह दिखना चाहिए (सभी मैंने किया है कि अद्यतन विशेषता को बदलना है)

<p:commandLink update="display" oncomplete="dlg.show()">
    <f:setPropertyActionListener value="#{lndInstrument}" 
        target="#{instrumentBean.selectedInstrument}" />
    <h:outputText value="#{lndInstrument.name}" />
</p:commandLink>  

मेरे वेब ऐप में यही काम करता है, और अगर यह आपके लिए काम नहीं करता है, तो मुझे लगता है कि आपके जावा बीन में कुछ गड़बड़ है ...


मैं आपको अपने उत्तर में (बंधन और चेहरे-विन्यास और अन्य के साथ) लिखे गए अन्य बदलावों को आज़माने की सलाह देता हूं। यह मानकर कि आपके "INFO: नहीं मिल सकता है ..." का हल निकालें
डैनियल

मैंने आपके 2 सुझाव को फिर से लागू करने की कोशिश की है, लेकिन यह अभी भी काम नहीं कर रहा है। संवाद खुलता है लेकिन इसमें चयनित आइटम का डेटा शामिल नहीं है। लॉग "पहचानकर्ता" दृश्य में "j_idt31" के साथ घटक नहीं ढूंढ सकता है, और मैं इससे अधिक कोई भी डीबग करने में सक्षम नहीं हूं।
रात

5

यह इसलिए है क्योंकि टैब एक नामकरण कंटेनर अस्वेल है ... आपका अपडेट होना चाहिए update="Search:insTable:display"कि आप क्या कर सकते हैं, यह आपके डायलॉग को फॉर्म के बाहर और अभी भी टैब के अंदर रखा गया है: यह होगा:update="Search:display"


0

को बदलने update="insTable:display"का प्रयास करें update="display"। मेरा मानना ​​है कि आप आईडी को उस तरह की आईडी के साथ उपसर्ग नहीं कर सकते।


2
बहुत पुराना लेकिन भ्रामक जवाब। ऊपर दिए गए BalusC के पोस्ट को देखें, स्पष्ट रूप से एक घटक की आईडी को संलग्न करने वाले फ़ॉर्म की आईडी के साथ प्रीफ़िक्सिंग दिखा रहा है: <h: फ़ॉर्म आईडी = "फ़ॉर्म"> <p: कमांड लिंक अपडेट = ": अन्य: परिणाम"> <! - ठीक है! -> </ h: फ़ॉर्म> <h: फॉर्म आईडी = "अन्यरूप"> <h: पैनलग्रुप आईडी = "परिणाम" /> </ h: फ़ॉर्म>
जे स्लीक

0

मुझे पता है कि इसका पहले से ही BalusC द्वारा एक शानदार जवाब है, लेकिन यहाँ एक छोटी सी चाल है जो मुझे सही क्लाइंटआईड बताने के लिए कंटेनर प्राप्त करने के लिए उपयोग करता है

  1. अपने घटक पर वह अपडेट निकालें जो काम नहीं कर रहा है
  2. जिस घटक को आप अपडेट करने का प्रयास कर रहे थे, उसके भीतर एक फर्जी अपडेट के साथ एक अस्थायी घटक रखें
  3. पृष्ठ को हिट करें, सर्वलेट अपवाद त्रुटि आपको सही क्लाइंट आईडी बताएगी जिसे आपको संदर्भित करने की आवश्यकता है।
  4. बोगस घटक निकालें और मूल अद्यतन में सही क्लाइंटआईड डालें

यहाँ कोड उदाहरण है क्योंकि मेरे शब्द इसे सर्वोत्तम नहीं बता सकते हैं।

<p:tabView id="tabs">
    <p:tab id="search" title="Search">                        
        <h:form id="insTable">
            <p:dataTable id="table" var="lndInstrument" value="#{instrumentBean.instruments}">
                <p:column>
                    <p:commandLink id="select"

इस घटक के भीतर विफलता अद्यतन निकालें

 oncomplete="dlg.show()">
                        <f:setPropertyActionListener value="#{lndInstrument}" 
                                        target="#{instrumentBean.selectedInstrument}" />
                        <h:outputText value="#{lndInstrument.name}" />
                    </p:commandLink>                                    
                </p:column>
            </p:dataTable>
            <p:dialog id="dlg" modal="true" widgetVar="dlg">
                <h:panelGrid id="display">

उस आईडी के घटक के भीतर एक घटक जोड़ें जिसे आप अपडेट करने का प्रयास कर रहे हैं जो विफल हो जाएगा

   <p:commandButton id="BogusButton" update="BogusUpdate"></p:commandButton>

                    <h:outputText value="Name:" />
                    <h:outputText value="#{instrumentBean.selectedInstrument.name}" />
                </h:panelGrid>
            </p:dialog>                            
        </h:form>
    </p:tab>
</p:tabView>

इस पृष्ठ को मारो और त्रुटि देखें। त्रुटि है: javax.servlet.ServletException: अभिव्यक्ति के लिए घटक "बोगसअपडेट" टैब से संदर्भित नहीं मिल सकता है : असंवेदनशील: बोगसबटन

तो सही ग्राहक का उपयोग करने के लिए तो बोल्ड प्लस लक्ष्य कंटेनर (इस मामले में प्रदर्शन) की आईडी होगी

tabs:insTable:display
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.