How to reuse the jsf component parameters? - jsf

I have code
<p:column id="columnLastComment" headerText="LAST COMM" width="80"
styleClass="long-field" filterStyleClass="flt-hidden"
style="#{alarmTable.getDisplayStatus('columnLastComment')}"
sortBy="#{alarm.lastComment}" filterBy="#{alarm.lastComment}">
<h:outputText value="#{alarm.lastComment}" />
<f:facet name="header">
<h:outputText value="LAST COMM" title="Last Comment"
styleClass="tableHeader-fontSize" />
</f:facet>
</p:column>
How i can use id of column in style value? example -
style="#{alarmTable.getDisplayStatus('[id of this column]')}"

Theoretically, you could get away with the implicit EL variable #{component} to get the current component, like so:
<h:outputText id="foo" styleClass="#{bean.styleClass(component.id)}" />
But, unfortunately, the UIColumn component has a special treatment. The #{component} refers the parent UIData component instead, which would in your case be the <p:dataTable>.
So, you've really to repeat it (like as you're already doing for the phrase "lastComment". You could maybe make it less painful by using a property of #{alarm}.

Related

update datatable footer primefaces (facet or columnGroup)

I want to make a footer in dataTable and I need to update when the values inside the DT changes.
The problem is that ajax update simply don't occurs.
I've tried two ways:
<p:dataTable
id="dataTableAvaliacao" var="aluno"
value="#{alunoAvaliacaoMB.alunos}">
<p:column>
<p:inputText id="inputNota"
value="#{aluno.getNota(avaliacao.property).vlNotaString}">
<p:ajax event="change"
update=":form:dataTableAvaliacao:mediaAluno, :form:dataTableAvaliacao:mediaAvaliacao" />
</p:inputText>
</p:column>
<p:columnGroup type="footer" id="mediaAvaliacao">
<p:row>
<p:column
footerText="Nota média da avaliação" />
</p:row>
<p:row>
<ui:repeat value="#{alunoAvaliacaoMB.colunasAvaliacoes}"
var="avaliacao">
<p:column id="colunaMedia"
footerText="#{alunoAvaliacaoMB.getMediaAvaliacao(avaliacao.property)}"/>
</ui:repeat>
</p:row>
</p:columnGroup>
<p:dataTable>
The update doesn't occurs...
second way (based on this answer on SO: How to ajax update an item in the footer of a PrimeFaces dataTable?):
<p:remoteCommand name="refreshFooter" update=":form:dataTableAvaliacao:outputMediaAvaliacao"/>
<p:dataTable
id="dataTableAvaliacao" var="aluno"
value="#{alunoAvaliacaoMB.alunos}">
<p:column>
<p:inputText id="inputNota"
value="#{aluno.getNota(avaliacao.property).vlNotaString}">
<p:ajax event="change"
update=":form:dataTableAvaliacao:mediaAluno" oncomplete="refreshFooter();" />
</p:inputText>
</p:column>
<p:dataTable>
<f:facet name="footer">
<h:outputText colspan="1" value="Nota média da avaliação:"/>
<ui:repeat value="#{alunoAvaliacaoMB.colunasAvaliacoes}"
var="avaliacao">
<h:outputText id="outputMediaAvaliacao"
value="#{alunoAvaliacaoMB.getMediaAvaliacao(avaliacao.property)}"
</ui:repeat>
</f:facet>
I've also tried
<p:remoteCommand name="refreshFooter" update=":form:outputMediaAvaliacao"/>
If I put
<p:ajax event="change"
update=":form:dataTableAvaliacao:mediaAluno, :form:dataTableAvaliacao" />
in the first way, it works, but I don't wanna update all dataTable every time.
What I'm doing wrong? is it a bug?
Referring on 2nd way from your question that you based on this answer...
actually it is possible to update p:dataTable footer (even from within table itself)...but with one modification of your code.
Reason why your implementation does not work is that you did not take into account that <h:outputText id="outputMediaAvaliacao"../> is wrapped with ui:repeat.
In that case, p:remoteCommand is not able to find h:outputText component ID defined in update attribute because that ID does not exist in DOM:
ui:repeat is actually copying h:outputText as many times as list from value attribute is long and appending all parent IDs to newly created native HTML components
<span id="form:dataTableAvaliacao:avaliacao:0:outputMediaAvaliacao">...</span>
<span id="form:dataTableAvaliacao:avaliacao:1:outputMediaAvaliacao">...</span>
<span id="form:dataTableAvaliacao:avaliacao:2:outputMediaAvaliacao">...</span>
...
(you can see the same using DOM inspector of your favorite browser)
SOLUTION
After you learn and understand all facts stated above (like I did :) ), solution is quite simple:
wrap ui:repeat with some parent element and assign ID to parent element. For example like this
<f:facet name="footer">
<h:outputText value="Nota média da avaliação:"/>
<h:panelGroup id="footerPanel">
<ui:repeat value="#{alunoAvaliacaoMB.colunasAvaliacoes}"
var="avaliacao" id="avaliacao">
<h:outputText id="outputMediaAvaliacao" value="#{alunoAvaliacaoMB.getMediaAvaliacao(avaliacao.property)}" />
</ui:repeat>
</h:panelGroup>
</f:facet>
and modify p:ajax of p:inputText to update newly created element after text is changed
<p:ajax event="change" update=":form:dataTableAvaliacao:footerPanel" />
On this way all children elements of h:panelGroup will be updated (meaning only footer will be updated and not entire table).
And now, after you solved updating, you can focus on designing of all UI elements under h:panelGroup to make them fit your requirements.

How to render a specific row in richfaces 4?

I have the following DataTable in richFaces 4.5.2:
<rich:dataTable id="t" var="v" rows="#{bean.size}"
value="#{bean.value}" rowKeyVar="row">
<rich:column>
<a4j:commandLink action="#{bean.doAction}" render="t:#{row}">
<h:outputText value="#{recipientGroup.id}" />
<f:facet name="footer">
<h:outputText value="#{msgs['dynamicRecipientGroupList.table.id']}"/>
</f:facet>
</rich:column>
</rich:dataTable>
I thought specifying the rowId explicitly force the richFaces to render the only specified row, but It renders the whole table instead. What did I do wrong?
New syntax is described here. (All data iteration components)
In your case it should be something like:
render="t:#rows(row)"

CommandLink with parameter in actionListener method doesn't work inside f:facet of datatable

I'd like to be able to click the headers in a table to sort the respective columns. When I try to do this with a h:commandLink and pass the column name as a parameter I get an error saying that the commandLink needs to be ended with > or />, which I do. Example:
<h:column>
<f:facet name="header">
<h:commandLink
value="name"
actionListener="#{albumListBean.sort("album_name")}">
</h:commandLink>
</f:facet>
<h:outputText value="#{item.name}" styleClass="tableItem" />
</h:column>
I get the same result using f:ajax or p:commandLink. If I remove the parameter however, I get no error (but of course the sorting doesn't work either).
Is it not allowed to pass a parameter this way inside the f:facet?
The strings inside EL expressions must be expressed inside simple cotes :
<h:commandLink
value="name"
actionListener="#{albumListBean.sort('album_name')}">
</h:commandLink>

p:selectOneMenu, custom content and editable=true

I have the following usage of the p:selectOneMenu:
<p:selectOneMenu id="selectField"
value="#{someBean.someField}"
converter="#{selectItemConverter}" var="x" editable="true">
<f:selectItems
value="#{selectItemsBean.getSelectItems(tab, field)}" var="si"
itemLabel="#{si.label}" itemValue="#{si}" />
<p:column>
<h:outputText value="#{si.label}" />
</p:column>
<p:column>
<h:graphicImage library="images" name="noway_16x16.png"
title="#{si.disabledReason}" rendered="#{si.disabled}" />
</p:column>
<p:ajax event="change" update="#form" partialSubmit="true" process="selectField" />
</p:selectOneMenu>
As you can see, I use custom content in combination with editable=true. When I submit the form, the Converter gets the label of a selected item as the value, not the actual value. In the HTML page, the values are correct, e.g. <option value="C">C-style mounting</option>. With editable=false, the correct value (e.g. C is sent to the converter, with editable=true the converter retrieves C-style mounting.
What I want is that the user can either select one of the pre-defined items in the list and the server submits that value of the item OR the user enters something and that is submitted as value. But the current behavior is a bit strange - or am I just wanting too much?

JSFpanelGrid dynamically populated

I want to render a panelGrid with a fixed number of columns but elements are loaded from a list. The code should be as follows:
<h:panelGrid columns="3">
<h:outputText value="Header 1"/>
<h:outputText value="Header 2"/>
<h:outputText value="Header 3"/>
<ui:repeat value="#{bean.collection}" var="obj">
<p:panel>
<h:outputText value="#{obj.value}"/>
</p:panel>
</ui:repeat>
</p:panelGrid>
The problem is this code is not rendering as I expected, because all panels are enclosed in the first TD generated by panelGrid, and I want a row break every 3 elements. It seems all repeat block is executed prior the rendering. I'm sure I can obtain this behaviour. What I'm doing wrong?
Thanks
ui:repeat is a component and it is part of the component tree. To create what you are planning try using tag handler c:forEach instead.
<c:forEach items="#{bean.collection}" var="obj">
<p:panel>
<h:outputText value="#{obj.value}"/>
</p:panel>
</c:forEach>

Resources