Sprawdź w wyjściu HTML rzeczywisty identyfikator klienta
Musisz spojrzeć na wygenerowany wynik HTML, aby znaleźć właściwy identyfikator klienta. Otwórz stronę w przeglądarce, kliknij prawym przyciskiem myszy i wyświetl źródło . Znajdź reprezentację HTML interesującego komponentu JSF i wybierz go id
jako identyfikator klienta. Możesz go używać w sposób bezwzględny lub względny, w zależności od bieżącego kontenera nazewnictwa. Patrz następny rozdział.
Uwaga: jeśli zdarzy się, że zawiera indeks iteracji, taki jak :0:
, :1:
itp. (Ponieważ znajduje się wewnątrz komponentu iterującego), musisz zdać sobie sprawę, że aktualizacja określonej rundy iteracji nie zawsze jest obsługiwana. Więcej szczegółów na ten temat znajduje się na dole odpowiedzi.
Zapamiętaj NamingContainer
komponenty i zawsze nadawaj im stały identyfikator
Jeśli komponent, do którego chcesz się odwoływać przez proces / wykonanie / aktualizację / renderowanie AJAX, znajduje się wewnątrz tego samego NamingContainer
rodzica, po prostu odwołaj się do jego własnego ID.
<h:form id="form">
<p:commandLink update="result"> <!-- OK! -->
<h:panelGroup id="result" />
</h:form>
Jeśli to nie wewnątrz taka sama NamingContainer
, to trzeba odwoływać się do niej za pomocą bezwzględnego identyfikator klienta. Bezwzględny identyfikator klienta zaczyna się od NamingContainer
znaku separatora, który jest domyślnie :
.
<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
Składniki są na przykład <h:form>
, <h:dataTable>
, <p:tabView>
, <cc:implementation>
(czyli wszystkie elementy kompozytowe), itp je łatwo rozpoznać patrząc na wyjściu generowany HTML, ich ID będzie dołączany do wygenerowanego ID klienta wszystkich elementów podrzędnych. Zwróć uwagę, że jeśli nie mają stałego identyfikatora, JSF użyje automatycznie wygenerowanego identyfikatora w j_idXXX
formacie. Należy tego bezwzględnie unikać, dając im stały identyfikator. W OmniFacesNoAutoGeneratedIdViewHandler
mogą być pomocne w tym czasie rozwoju.
Jeśli wiesz, jak znaleźć javadoc, o którym UIComponent
mowa, możesz również sprawdzić, czy implementuje on NamingContainer
interfejs, czy nie. Na przykład HtmlForm
( tag UIComponent
za <h:form>
) pokazuje, że implementuje NamingContainer
, ale HtmlPanelGroup
( tag UIComponent
za <h:panelGroup>
) go nie pokazuje, więc nie implementuje NamingContainer
. Oto javadoc wszystkich standardowych komponentów, a tutaj javadoc PrimeFaces .
Rozwiązanie twojego problemu
Więc w twoim przypadku:
<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">
Wygenerowany wynik HTML <h:panelGrid id="display">
wygląda następująco:
<table id="tabs:insTable:display">
Musisz wziąć dokładnie to id
jako identyfikator klienta, a następnie przedrostek :
do użycia w update
:
<p:commandLink update=":tabs:insTable:display">
Odwołanie poza include / tagfile / composite
Jeśli to łącze polecenia znajduje się wewnątrz pliku include / tagfile, a cel znajduje się poza nim, a zatem niekoniecznie znasz identyfikator nadrzędnego kontenera nazewnictwa bieżącego kontenera nazewnictwa, możesz dynamicznie odwoływać się do niego w następujący UIComponent#getNamingContainer()
sposób:
<p:commandLink update=":#{component.namingContainer.parent.namingContainer.clientId}:display">
Lub, jeśli to łącze polecenia znajduje się wewnątrz komponentu złożonego, a cel znajduje się poza nim:
<p:commandLink update=":#{cc.parent.namingContainer.clientId}:display">
Lub, jeśli zarówno łącze polecenia, jak i cel znajdują się wewnątrz tego samego komponentu złożonego:
<p:commandLink update=":#{cc.clientId}:display">
Zobacz także Pobierz identyfikator nadrzędnego kontenera nazewnictwa w szablonie dla atrybutu renderowania / aktualizacji
Jak to działa pod kołdrą
To wszystko jest określona jako „szukaj wyrażenia” w tym UIComponent#findComponent()
javadoc :
Wyrażenie wyszukiwania składa się albo z identyfikatorem (która jest dopasowana dokładnie przeciwko własności identyfikator ID UIComponent
lub serii takich identyfikatorów połączonych przez UINamingContainer#getSeparatorChar
wartości znaków. Algorytm wyszukiwania powinien działa następująco, choć alternatywne alogrithms mogą być stosowane tak długo, jak efekt końcowy jest taki sam:
- Zidentyfikuj,
UIComponent
który będzie podstawą wyszukiwania, zatrzymując się, gdy tylko zostanie spełniony jeden z następujących warunków:
- Jeśli wyrażenie wyszukiwania zaczyna się od znaku separatora (zwanego „absolutnym” wyrażeniem wyszukiwania), podstawą będzie korzeń
UIComponent
drzewa komponentów. Początkowy separator zostanie usunięty, a pozostała część wyszukiwanego wyrażenia będzie traktowana jako „względne” wyrażenie wyszukiwania, jak opisano poniżej.
- W przeciwnym razie, jeśli
UIComponent
jest NamingContainer
to podstawa, będzie służyć jako podstawa.
- W przeciwnym razie wyszukaj elementy nadrzędne tego składnika. Jeśli
NamingContainer
zostanie napotkany, będzie bazą.
- W przeciwnym razie (jeśli nie
NamingContainer
zostanie napotkany) root UIComponent
będzie podstawą.
- Wyrażenie wyszukiwania (prawdopodobnie zmodyfikowane w poprzednim kroku) jest teraz „względnym” wyrażeniem wyszukiwania, które zostanie użyte do zlokalizowania komponentu (jeśli istnieje), którego identyfikator jest zgodny, w zakresie komponentu podstawowego. Mecz przebiega w następujący sposób:
- Jeśli wyrażenie wyszukiwania jest prostym identyfikatorem, ta wartość jest porównywana z właściwością id, a następnie rekurencyjnie przez aspekty i elementy podrzędne podstawy
UIComponent
(z wyjątkiem tego, że jeśli NamingContainer
zostanie znaleziony element podrzędny , jego własne aspekty i elementy potomne nie są przeszukiwane).
- Jeśli wyrażenie wyszukiwania zawiera więcej niż jeden identyfikator oddzielony znakiem separatora, pierwszy identyfikator jest używany do zlokalizowania a
NamingContainer
według reguł z poprzedniego punktu. Następnie zostanie wywołana findComponent()
metoda tego NamingContainer
, przekazując pozostałą część wyszukiwanego wyrażenia.
Zauważ, że PrimeFaces również stosuje się do specyfikacji JSF, ale RichFaces używa „kilku dodatkowych wyjątków” .
„reRender” używa UIComponent.findComponent()
algorytmu (z pewnymi dodatkowymi wyjątkami) do znalezienia komponentu w drzewie komponentów.
Te dodatkowe wyjątki nie są nigdzie szczegółowo opisane, ale wiadomo, że względne identyfikatory komponentów (tj. Te, które nie zaczynają się od :
) są wyszukiwane nie tylko w kontekście najbliższego rodzica NamingContainer
, ale także we wszystkich innych NamingContainer
komponentach w tym samym widoku (co jest względnie droga praca przy okazji).
Nigdy nie używaj prependId="false"
Jeśli to wszystko nadal nie działa, sprawdź, czy nie używasz <h:form prependId="false">
. To się nie powiedzie podczas przetwarzania przesyłania i renderowania Ajax. Zobacz także to pokrewne pytanie: UIForm z prependId = "false" przerywa <f: ajax render> .
Odwoływanie się do określonej rundy iteracji składników iteracyjnych
Przez długi czas nie było możliwe odniesienie się do konkretnego iterowanego elementu w iteracyjnych komponentach, takich jak <ui:repeat>
i <h:dataTable>
podobne:
<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>
Jednak od czasu, gdy Mojarra 2.2.5 <f:ajax>
zaczął go obsługiwać (po prostu przestał go sprawdzać; w ten sposób nigdy więcej nie spotkałbyś się z wymienionym w pytaniu wyjątkiem; kolejne ulepszenie jest planowane później).
Nie działa to jeszcze tylko w aktualnych wersjach MyFaces 2.2.7 i PrimeFaces 5.2. Wsparcie może pojawić się w przyszłych wersjach. W międzyczasie najlepiej jest zaktualizować sam komponent iterujący lub element nadrzędny, jeśli nie renderuje HTML, na przykład <ui:repeat>
.
Korzystając z PrimeFaces, rozważ wyrażenia wyszukiwania lub selektory
PrimeFaces Search Expressions umożliwia odwoływanie się do komponentów poprzez wyrażenia wyszukiwania w drzewie komponentów JSF. JSF ma kilka wbudowanych:
@this
: obecny składnik
@form
: rodzic UIForm
@all
: cały dokument
@none
: nic
PrimeFaces rozszerzył to o nowe słowa kluczowe i obsługę wyrażeń złożonych:
@parent
: składnik macierzysty
@namingcontainer
: rodzic UINamingContainer
@widgetVar(name)
: składnik określony przez podany widgetVar
Można też mieszać te słowa kluczowe w wyrażeniach złożonych, takich jak @form:@parent
, @this:@parent:@parent
itp
PrimeFaces Selectors (PFS) as in @(.someclass)
umożliwia odwoływanie się do komponentów za pomocą składni selektora jQuery CSS. Np. Odwoływanie się do komponentów mających wszystkie wspólne klasy stylów w wyjściu HTML. Jest to szczególnie przydatne w przypadku, gdy trzeba odwołać się do „wielu” komponentów. Wymaga to tylko, aby komponenty docelowe miały cały identyfikator klienta w wyjściu HTML (stały lub wygenerowany automatycznie, nie ma znaczenia). Zobacz także Jak działają selektory PrimeFaces, jak w update = "@ (. MyClass)"?
context.getViewRoot().findComponent(":inputform" + UINamingContainer.getSeparatorChar(context) + "inputtext" );
Dołącz również kod xhtml.prependId="false"
zapisaniem mojego dnia.po pierwsze: o ile wiem, umieszczanie okna dialogowego w widoku tabulatora jest złą praktyką ... lepiej to wyjmij ...
a teraz na twoje pytanie:
przepraszam, zajęło mi trochę czasu, aby uzyskać to, co dokładnie chciałeś zaimplementować,
zrobiłem w mojej aplikacji internetowej i to działa
jak powiedziałem wcześniej umieść p: dialog poza `p: tabView,
zostaw okno dialogowe p: tak, jak sugerowałeś na początku:
a p: commandlink powinien wyglądać tak (wszystko, co zrobiłem, to zmienić atrybut aktualizacji)
to samo działa w mojej aplikacji internetowej, a jeśli to nie zadziała, to chyba coś jest nie tak w kodzie java bean ...
źródło
Dzieje się tak, ponieważ karta jest również kontenerem nazewnictwa ... Twoja aktualizacja powinna być
update="Search:insTable:display"
To, co możesz zrobić, to po prostu umieścić swoje okno dialogowe poza formularzem i nadal wewnątrz karty, wtedy wyglądałoby to tak:update="Search:display"
źródło
Spróbuj zmienić
update="insTable:display"
naupdate="display"
. Uważam, że nie można poprzedzić identyfikatora takim identyfikatorem formularza.źródło
Wiem, że to już ma świetną odpowiedź od BalusC, ale tutaj jest mała sztuczka, której używam, aby kontener podał mi poprawny clientId .
Oto przykład kodu, ponieważ moje słowa mogą go nie opisać najlepiej.
Usuń nieudaną aktualizację w tym komponencie
Dodaj składnik w składniku identyfikatora, który próbujesz zaktualizować, za pomocą aktualizacji, która się nie powiedzie
Wejdź na tę stronę i zobacz błąd. Wystąpił błąd: javax.servlet.ServletException: Nie można znaleźć komponentu wyrażenia „BogusUpdate”, do którego odwołuje się zakładka: insTable: BogusButton
Zatem prawidłowy identyfikator clientId do użycia byłby pogrubiony plus identyfikator kontenera docelowego (w tym przypadku wyświetlany)
źródło