Click event on div in JSF2 - ajax

I have a list represented by a ui:repeat, where each item is a div with some data. What I want is to show the item detail by clicking on the div.
I made it with a button refreshing the form but can't make it work with onclick event on panelGroup.
<h:panelGroup styleClass="container" layout="block">
<ui:repeat value="#{bean.model}" var="item">
<h:panelGroup styleClass="item_data" layout="block">
ID: #{item.id}
<h:commandButton action="#{bean.select}" value="Select item">
<f:param name="itemId" value="#{item.id}"/>
<f:ajax render="#form"></f:ajax>
</h:commandButton>
</h:panelGroup>
<h:panelGroup styleClass="detail"
layout="block"
rendered="#{item eq bean.selected}">
value: #{bean.selected.value}
</h:panelGroup>
</ui:repeat>
</h:panelGroup>

If I understand you correctly, you just want to show the detail section without re-rendering the whole form? If so, then wrap it in a component which is always rendered in the HTML DOM tree, give it an id and refer it instead:
<ui:repeat value="#{bean.model}" var="item">
<h:panelGroup styleClass="item_data" layout="block">
ID: #{item.id}
<h:commandButton action="#{bean.select}" value="Select item">
<f:param name="itemId" value="#{item.id}"/>
<f:ajax render="detail" />
</h:commandButton>
</h:panelGroup>
<h:panelGroup id="detail">
<h:panelGroup styleClass="detail"
layout="block"
rendered="#{item eq bean.selected}">
value: #{bean.selected.value}
</h:panelGroup>
</h:panelGroup>
</ui:repeat>
See also:
Communication in JSF 2.0 - Ajax rendering of content which is by itself conditionally rendered
Update: as per the comments, you actually want to invoke JSF ajax action by <h:panelGroup onclick> no, that's not possible as it doesn't support onclick attribute. You could use a <div> with jsf.ajax.request() function, but cleaner would be to use a <h:commandLink> with CSS display: block so that it spans the entire div.
<h:panelGroup styleClass="item_data" layout="block">
<h:commandLink action="#{bean.select}" value="ID: #{item.id}" styleclass="detailLink">
<f:param name="itemId" value="#{item.id}"/>
<f:ajax render="detail" />
</h:commandLink>
</h:panelGroup>
with e.g.
.detailLink {
display: block;
color: black;
text-decoration: none;
}

Related

Parts which are ajax-rendered after actions doesn't work fine unless you reload the page

The fist time I go to the JSF page and I make an action for rendering some parts of the page, those parts are not rendering anymore. However, if you reload the page, thats areas are rendering fine.
For me, it seems that first time the page is constructed the ids are not prepended correctly. That causes the Jboss server to ignore every posted value because it cannot find a concurrent element in the site.
Reloading the page solves the problem with the false prepending of the ids.
I don't know because this, someone got the same problem? I have tried to solve it, but I was impossible.
Here you have the code:
<h:form id="select" styleClass="applic_filterside" binding="#{companyOverview2.selectForm}">
<a4j:region>
<h:panelGroup layout="block" styleClass="applic_filter_selectrow">
<tibuga:selectManyCheckbox label="Branche:" valueBean="#{companyOverview2}" valueProperty="selectedSectorID"
id="selSec" items="#{generalData.allSectors}" itemValue="#{c.id}" var="c" itemLabel="#{c.name}" width="174"
showButtonsSelectAll="false" display="none">
<a4j:ajax event="click" onbegin="submitSearch();"></a4j:ajax>
</tibuga:selectManyCheckbox>
</h:panelGroup>
<h:panelGroup layout="block" styleClass="applic_filter_selectrow">
<a4j:commandLink action="#{companyOverview2.filterSearchEntrys()}" onclick="flushInputs(this);" oncomplete="turnInputs(document.getElementById('select:button'));"
render="companyTableNew" execute="#form" limitRender="true" id="button">
<h:graphicImage value="/resources/images/fields/filter.png" />
</a4j:commandLink>
</h:panelGroup>
</a4j:region>
</h:form>
<h:panelGroup id="companyTableNew" >
<h:form>
<h:panelGroup layout="block" styleClass="applic_filter_countrow">
<h:outputText value="Treffer: #{companyOverview2.count()} Unternehmen" />
</h:panelGroup>
<a4j:region>
<h:panelGroup layout="block" id="cont" styleClass="applic_applicants">
<h:panelGroup layout="block" styleClass="top_line">
<h:panelGroup layout="block" styleClass="sectors">
<h:outputText value="Branche" />
</h:panelGroup>
<h:panelGroup layout="block" styleClass="location">
<h:outputText value="Standort" />
</h:panelGroup>
<h:panelGroup layout="block" styleClass="size">
<h:outputText value="Größe" />
</h:panelGroup>
</h:panelGroup>
<ui:repeat value="#{companyOverview2.filteredCompanysNew}" var="a">
<tibuga:singleCompanyEntry entry="#{a}" />
</ui:repeat>
<h:panelGroup layout="block" styleClass="companys_actions">
<a4j:commandLink value="weitere Unternehmen anzeigen ..." action="#{companyOverview2.showMore()}" render="companyTableNew" rendered = "#{companyOverview2.showMoreLink}"/>
</h:panelGroup>
</h:panelGroup>
</a4j:region>
</h:form>
</h:panelGroup>
The problem is that the first time that you go to the page, you can see the results correctly, but if you make a query the datas from CompanyTableNew are wrong, but reloading the page all is right.

How to use p:ajax to update several components in order

I'm trying to render the following JSF page:
<h:form id="form" prependId="false">
<h:panelGrid width="100%">
<h:panelGroup id="tableDiv" layout="block">
<h:panelGroup layout="block" style="text-align: center;">
<p:dataTable id="table" var="_item"
value="#{primeBean.findTableModel()}">
...
</p:dataTable>
</h:panelGroup>
</h:panelGroup>
<h:panelGrid columns="2" width="100%">
<h:panelGroup id="barChartDiv" layout="block">
<p:barChart id="barChart"
value="#{primeBean.findCartesianModel()}">
<p:ajax event="itemSelect" listener="#{primeBean.handleItemSelect}"
update="pieChartDiv,tableDiv" />
</p:barChart>
</h:panelGroup>
<h:panelGroup id="pieChartDiv" layout="block">
<h:panelGroup layout="block">
<p:pieChart id="pieChart">
<p:ajax event="itemSelect" listener="#{primeBean.handleItemSelect}"
update="tableDiv" />
</p:pieChart>
</h:panelGroup>
</h:panelGroup>
</h:panelGrid>
</h:panelGrid>
</h:form>
When I click in any bar on p:barChart, I expect that the components in the update attribute would be rendered in the order that I declare (pieChartDiv,tableDiv), but they are rendered in reverse order (tableDiv,pieChartDiv).
Is this normal behavior? How can I update a component list in the order the items are declared?
That's not possible this way. The components are searched and updated in exactly the same order as they appear in the JSF component tree.
One way would be to rearrange/swap the both components in the tree hierarchy and reposition them visually with help of CSS. This is however rather clumsy.
Another way would be to update the 2nd component on complete of the update of the 1st component (and thus effectively end up with 2 ajax requests instead of 1). You can achieve that with help of <p:remoteCommand> which is invoked on complete of the <p:ajax>.
So, instead of
<p:ajax ... update="pieChartDiv,tableDiv" />
use
<p:ajax ... update="pieChartDiv" oncomplete="updateTableDiv()" />
...
<p:remoteCommand name="updateTableDiv" update="tableDiv" />
Not so elegant but working solution can be this:
<p:barChart id="barChart"
value="#{primeBean.findCartesianModel()}">
<p:ajax event="itemSelect" listener="#{primeBean.handleItemSelect}"
update="pieChartDiv" /> <!-- This will be updated as first. -->
<p:ajax event="itemSelect"
update="tableDiv" /> <!-- And this will be updated as second. -->
</p:barChart>

Jsf2 ajax render id not found

Why i get " contains an unknown id ':commentTextArea' - cannot locate it in the context of the component commentLink" error?
majorra 2.1.7
How i can render commentTextArea.
<ui:repeat var="parentComment" value="#{commentTree.parentCommentsWrapper}"> ....
<h:form>
<h:commandLink id="commentLink" value="comment"
style="height:20px;width:20px;padding: 0; margin: 0;"
action="#{parentComment.changeEditable}">
**<f:ajax render=":commentTextArea"></f:ajax>**
</h:commandLink>
</h:form> <h:panelGroup id="commentTextArea">
<br />
<h:panelGroup rendered="#{parentComment.editable}">
<h:form >
<h:inputTextarea rows="2" cols="20"
value="#{commentTree.newCommentText}"
style="font-family:Arial,Helvetica;font-size:12px;width:365px;margin-right: 4px;margin-left: -1px;">
</h:inputTextarea>
<h:commandButton id="newCommentButton" value="+"
style="height:20px;width:20px;padding: 0; margin: 0;"
action="#{commentTree.saveChildComment(parentComment.comment)}" >
</h:commandButton>
</h:form>
</h:panelGroup>
</h:panelGroup>
</ui:repeat>
'
The id :commentTextArea is an absolute id and relative to the view root. However, ui:repeat is a NamingContainer and "wraps" your commentTextArea. (Check the html source in browser to see what id is generated)
A simple solution would be to use only one form in your 'ui:repeat'. Then the relative id with
<f:ajax render="commentTextArea">
(without :) would work.

JSF and ajax: listener of dynamically added component never tirggered

I have got a problem with my JSF application.
On a page there's a form where the user can dynamically add components to that very same form. When I use the ajax listener to add the component, it is updated in the view and also in the model. But when I try to remove the dynamiccaly added component by pressing an h:actionLink its ajax listener is never triggered.
This is my code:
<h:form rendered="#{schrijvenController.verslagenController.documentSelected}">
<p>
<span class="noLabel">
#{bundle.JongereJongere}:
</span>
<h:selectOneMenu id="jongereSelect" valueChangeListener="#{schrijvenController.selecteerJongere}" immediate="true"
value="#{schrijvenController.currentJongere.jongereID}"
title="--#{bundle.JongereSelect}--">
<f:selectItems value="#{jongereController.jongerenAsSelectItems}"/>
</h:selectOneMenu>
</p>
<h:panelGroup id="personen">
<ui:repeat value="#{schrijvenController.verslagenController.persoonItems}" var="persoon">
<div class="div_add_persoon">
<div class="div_add_persoon_left">
<span class="noLabel"> #{persoon.aanwezigheid}:</span>
<h:inputText value="#{persoon.searchTerm}"
onkeypress="if (event.keyCode == 13) { onchange(); return false; }">
<f:ajax event="keypress" render="persoonLijst" listener="#{persoon.getPersonenWhereNameLikeSelectItems}" />
</h:inputText>
<h:selectOneMenu id="persoonLijst" styleClass="fixedWitdhDropDown"
value="#{persoon.currentPersoon.persoon_id}"
title="--#{bundle.PersoonSelect}--">
<f:selectItems value="#{persoon.personenWhereNameLikeSelectItems}"/>
<f:ajax event="change" render="#form" listener="#{persoon.add}" />
</h:selectOneMenu>
</div>
<h:panelGroup layout="block" styleClass="div_add_persoon_right">
<ui:repeat value="#{persoon.personen}" var="persoonPersoon">
<h:panelGroup layout="block" styleClass="div_schrijvenPersoon">
<h:outputText value=" #{persoonPersoon.naam} #{persoonPersoon.voornaam} " />
<h:commandLink value="X" id="linkske">
<f:ajax event="click" render="#form" listener="#{persoon.delete}" />
</h:commandLink>
</h:panelGroup>
</ui:repeat>
</h:panelGroup>
</div>
</ui:repeat>
<div class="clear" />
This is a Prt Sc of my view:
http://i206.photobucket.com/albums/bb69/bartloterman/pscreen.jpg?t=1302028364
If one clicks on an element from the list, it's added to the right inside a div together with a commandLink with the text "x". But when I click the "x" link nothing happens (no function is being executed). It is as if the view can't find the component. I'm using Datamodels.
I've been looking all day for a solution on the web but I couldn't find one. Any help would be greatly appreciated.
I managed to solve the problem by using the following code in my view
<h:commandLink value="X">
<f:ajax render="#form" execute="#form" listener="#{persoon.delete}" />
</h:commandLink>
Seems I needed render="#form" and execute="#form"

JSF - An ajaxsupport question

Specifically I refer to this example:
<h:panelgroup>
<a4j:support event="onlick" action="do1"/>
<h:commandbutton id="1".../>
<h:commandbutton id="2".../>
<h:commandbutton id="3"...>
<a4j:support event="onlick" action="do2"/>
</h:commandbutton>
</h:panelgroup>
My questions -
If I click one of the buttons in the panelgroup, will do1() fire?
If I click the third button will do1() and do2() fire? (What'll happen?)
I'm asking instead of just trying in a sandbox because I hope to understand a little behind the scenes why the specific behavior occurs.
Thanks!
Ok. Tested it and this is the result:
For this Code:
<h:form>
<h:panelGrid>
<h:panelGrid style="border: 1px solid #000;">
<h:outputText value="Panel1" />
<a4j:support event="onclick" action="#{mrBean.doSupport1}" />
<h:commandButton action="#{mrBean.doButton}">
</h:commandButton>
<h:panelGrid style="border: 1px solid #000;">
<h:outputText value="Panel2" />
<a4j:support event="onclick" action="#{mrBean.doSupport2}" />
</h:panelGrid>
</h:panelGrid>
</h:panelGrid>
</h:form>
If I click in panel1 I get:
doSupport1 runs.
If I clock on the button I get:
doSupport1 runs.
doButton runs.
If I click in panel2 I get:
doSupport1 runs.
doSupport2 runs.
So the answer to my question is that all support objects catch events and the order they are called is from father to son.

Resources