jsf - How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar" -


the following code inspired primefaces datagrid + datatable tutorials , put <p:tab> of <p:tabview> residing in <p:layoutunit> of <p:layout>. here inner part of code (starting p:tab component); outer part trivial.

<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> 

when click <p:commandlink>, code stops working , gives message:

cannot find component expression "instable:display" referenced "tabs:instable:select".

when try same using <f:ajax>, fails different message telling same:

<f:ajax> contains unknown id "instable:display" cannot locate in context of component "tabs:instable:select"

how caused , how can solve it?

look in html output actual client id

you need in generated html output find out right client id. open page in browser, rightclick , view source. locate html representation of jsf component of interest , take id client id. can use in absolute or relative way depending on current naming container. see following chapter.

note: if happens contain iteration index :0:, :1:, etc (because it's inside iterating component), need realize updating specific iteration round not supported. see bottom of answer more detail on that.

memorize namingcontainer components , give them fixed id

if component you'd reference ajax process/execute/update/render inside same namingcontainer parent, reference own id.

<h:form id="form">     <p:commandlink update="result"> <!-- ok! -->     <h:panelgroup id="result" /> </h:form> 

if it's not inside same namingcontainer, need reference using absolute client id. absolute client id starts namingcontainer separator character, default :.

<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 components example <h:form>, <h:datatable>, <p:tabview>, <cc:implementation> (thus, composite components), etc. recognize them looking @ generated html output, id prepended generated client id of child components. note when don't have fixed id, jsf use autogenerated id in j_idxxx format. should absolutely avoid giving them fixed id. omnifaces noautogeneratedidviewhandler may helpful in during development.

if know find javadoc of uicomponent in question, can check in there whether implements namingcontainer interface or not. example, htmlform (the uicomponent behind <h:form> tag) shows implements namingcontainer, htmlpanelgroup (the uicomponent behind <h:panelgroup> tag) not show it, not implement namingcontainer. here javadoc of standard components , here javadoc of primefaces.

solving problem

so in case of:

<p:tabview id="tabs"><!-- namingcontainer -->     <p:tab id="search"><!-- not namingcontainer -->         <h:form id="instable"><!-- namingcontainer -->             <p:dialog id="dlg"><!-- not namingcontainer -->                 <h:panelgrid id="display"> 

the generated html output of <h:panelgrid id="display"> looks this:

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

you need take id client id , prefix : usage in update:

<p:commandlink update=":tabs:instable:display"> 

referencing outside include/tagfile/composite

if command link inside include/tagfile, , target outside it, , don't know id of naming container parent of current naming container, can dynamically reference via uicomponent#getnamingcontainer() so:

<p:commandlink update=":#{component.namingcontainer.parent.namingcontainer.clientid}:display"> 

or, if command link inside composite component , target outside it:

<p:commandlink update=":#{cc.parent.namingcontainer.clientid}:display"> 

or, if both command link , target inside same composite component:

<p:commandlink update=":#{cc.clientid}:display"> 

see get id of parent naming container in template in render / update attribute

how work under covers

this specified "search expression" in the uicomponent#findcomponent() javadoc:

a search expression consists of either identifier (which matched against id property of uicomponent, or series of such identifiers linked uinamingcontainer#getseparatorchar character value. search algorithm should operates follows, though alternate alogrithms may used long end result same:

  • identify uicomponent base searching, stopping 1 of following conditions met:
    • if search expression begins the separator character (called "absolute" search expression), base root uicomponent of component tree. leading separator character stripped off, , remainder of search expression treated "relative" search expression described below.
    • otherwise, if uicomponent namingcontainer serve basis.
    • otherwise, search parents of component. if namingcontainer encountered, base.
    • otherwise (if no namingcontainer encountered) root uicomponent base.
  • the search expression (possibly modified in previous step) "relative" search expression used locate component (if any) has id matches, within scope of base component. match performed follows:
    • if search expression simple identifier, value compared id property, , recursively through facets , children of base uicomponent (except if descendant namingcontainer found, own facets , children not searched).
    • if search expression includes more 1 identifier separated separator character, first identifier used locate namingcontainer rules in previous bullet point. then, findcomponent() method of namingcontainer called, passing remainder of search expression.

note primefaces adheres jsf spec, richfaces uses "some additional exceptions".

"rerender" uses uicomponent.findcomponent() algorithm (with additional exceptions) find component in component tree.

those additional exceptions in detail described, it's known relative component ids (i.e. not starting :) not searched in context of closest parent namingcontainer, in other namingcontainer components in same view (which relatively expensive job way).

never use prependid="false"

if still doesn't work, verify if aren't using <h:form prependid="false">. fail during processing ajax submit , render. see related question: uiform prependid="false" breaks <f:ajax render>.

referencing specific iteration round of iterating components

it long time not possible reference specific iterated item in iterating components <ui:repeat> , <h:datatable> so:

<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> 

however, since mojarra 2.2.5 <f:ajax> started support (it stopped validating it; never face in question mentioned exception anymore; enhancement fix planned later).

this doesn't work yet in current myfaces 2.2.7 , primefaces 5.2 versions. support might come in future versions. in meanwhile, best bet update iterating component itself, or parent in case doesn't render html, <ui:repeat>.

when using primefaces, consider search expressions or selectors

primefaces search expressions allows reference components via jsf component tree search expressions. jsf has several builtin:

  • @this: current component
  • @form: parent uiform
  • @all: entire document
  • @none: nothing

primefaces has enhanced new keywords , composite expression support:

  • @parent: parent component
  • @namingcontainer: parent uinamingcontainer
  • @widgetvar(name): component identified given widgetvar

you can mix keywords in composite expressions such @form:@parent, @this:@parent:@parent, etc.

primefaces selectors (pfs) in @(.someclass) allows reference components via jquery css selector syntax. e.g. referencing components having common style class in html output. particularly helpful in case need reference "a lot of" components. prerequires target components have client id in html output (fixed or autogenerated, doesn't matter). see how primefaces selectors in update="@(.myclass)" work?


Comments

Popular posts from this blog

c++ - llvm function pass ReplaceInstWithInst malloc -

Cross-Compiling Linux Kernel for Raspberry Pi - ${CCPREFIX}gcc -v does not work -

java.lang.NoClassDefFoundError When Creating New Android Project -