how to get selected value of p:column of p:dataTable - jsf

I want to get selected value of p:column of p:datatable by using javascript(jquery). Do you think is that possible ? I tried several ways but I could not succeed. Any help will be great.
Regards
Here is the sample Code :
<p:dataTable id="attachmentsTable" var="dataRow" value="#{taslakFaturaBean.attachments}" style="width:980px; text-align:center;">
<p:column headerText="ID">
#{dataRow.AttachID}
</p:column>
<p:column headerText="Dosya Tarihi">
#{dataRow.AttachDate}
</p:column>
<p:column headerText="Dosya">
<p:commandButton id="downloadLink" value="İndir" icon="ui-icon-arrowthichk-s" rendered="#{not empty dataRow.AttachData}" ajax="false">
</p:commandButton>
</p:column>
I want to get selected p:column's AttachId when I click downloadLink commondButton by javascript.

If you want pure javascript I think it can be by this way
<script type="text/javascript">
function test(attachId) {
// get attachId
}
</script>
and in your dataTable like this
<input type="button" onlcick="test(#{dataRow.AttachID});" value="GetID" />
if you want to use commandButton you can try to use onclick="test(#{dataRow.AttachID})" but not sure about that :)

Related

Primefaces datatable update datatable

I have a problem with primefaces datatables. I have one datatable with some entries and a column with a button inside. If the button is pressed a popup is opened with another datatable. The entries in the second datatable are depending on the row in which the button is pressed.
<!-- first datatable -->
<h:form id="list">
<p:dataTable id="list1" var="item" value="#{bean1.itemlist}"
rowKey="#{item.id}" selection="#{bean1.selectedItem}"
selectionMode="single">
<p:column headerText="ID">
<h:outputText value="#{item.id}" />
</p:column>
...
<p:column headerText="Edit Entries">
<p:commandButton value="Edit Entries"
actionListener="#{bean2.updateEntries(item)}" ajax="true"
oncomplete="PF('edit_entries').show()" />
</p:column>
</p:dataTable>
<!-- Second datatable in the popup -->
<p:dialog header="Edit Entries" widgetVar="edit_entries" modal="true"
resizable="false">
<p:dataTable id="list2" var="entry"
value="#{bean2.entriesList}" rowKey="#{entry.id}"
selection="#{bean2.selectedEntry}" selectionMode="single">
<p:column headerText="Entry Number">
<h:outputText value="#{entry.number}" />
</p:column>
</p:dataTable>
<f:facet name="footer">
<p:commandButton value="Save" oncomplete="PF('edit_entries').hide()" />
</f:facet>
</p:dialog>
</form>
Bean2
public void updateEntries(Item selectedItem) {
this.entriesList = this.entriesQuery.getAllEntriesByItemID(selectedItem.getId());//db query could take some time
System.out.println("entrieslist size: " + this.entriesList.size()); //prints the correct size
}
The problem is that there are no entries listed in the popup datatable although there are some in the list after the db query.
Any ideas how to fix this bug?
Thanks in advance!
UPDATE 1:
<!-- first datatable -->
<h:form id="list">
<p:dataTable id="list1" var="item" value="#{bean1.itemlist}"
rowKey="#{item.id}" selection="#{bean1.selectedItem}"
selectionMode="single">
<p:column headerText="ID">
<h:outputText value="#{item.id}" />
</p:column>
...
<p:column headerText="Edit Entries">
<p:commandButton value="Edit Entries" update=":dialogUpdateEntries"
actionListener="#{bean2.updateEntries(item)}" ajax="true"
oncomplete="PF('edit_entries').show()" />
</p:column>
</p:dataTable>
</h:form>
<!-- Second datatable in the popup -->
<p:dialog header="Edit Enries" id="dialogUpdateEntries" widgetVar="edit_entries" modal="true"
resizable="false">
<h:form id="formEntriesList">
<p:dataTable id="list2" var="entry"
value="#{bean2.entriesList}" rowKey="#{entry.id}"
selection="#{bean2.selectedEntry}" selectionMode="single">
<p:column headerText="Entry Number">
<h:outputText value="#{entry.number}" />
</p:column>
</p:dataTable>
<f:facet name="footer">
<p:commandButton value="Save" oncomplete="PF('edit_entries').hide()" />
</f:facet>
</form>
</p:dialog>
You're indeed not updating the data table in the dialog. JSF doesn't automatically update the view on change of the model, you have to explicitly tell the view to do so. You can use the ajax action component's update attribute for this. This takes a JSF client ID which can be found by rules as outlined in this related answer: How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar".
Given the markup as shown in the question, that'll be
<p:commandButton ... update=":list:list2" />
However, there's another potential problem. You're using <p:dialog modal="true"> inside a form instead of giving the dialog its own form. This way the dialog may not be available in the HTML DOM tree as JavaScript (the one responsible for dealing with ajax stuff) would expect to find it. Giving the dialog its own form should fix this matter. It'll also fix the potential future problems with invoking actions from inside the dialog as handled in this related question: <p:commandbutton> action doesn't work inside <p:dialog>.
<h:form id="viewForm">
...
<p:commandButton ... update=":editDialog" />
...
</h:form>
<p:dialog id="editDialog" modal="true">
<h:form id="editForm">
...
</h:form>
</p:dialog>
Try adding update="list2" to Edit Entries command button (even update="#widgetVar(edit_entries)" should work).
If, because of page layout and structure, you can't target the second datatable using above suggestions, then add styleClass="tList2" to second table, and update it with update="#(.tList2)" on edit button.

How can I show watermark in data table filter?

I have a <p:column> with a filter.
I would like to show it with a watermark.
This is what I have tried:
<p:column id="carType" filterBy="#{car.carType}" >
<h:outputText value="#{car.carType}" />
<p:watermark forElement="carType"
value="Car Type"/>
</p:column>
However, that didn't show up. How can I achieve this?
Try this
<h:form id="parametersListForm">
<p:dataTable id="parameteresList" value="#{parameterController.lstParameter}"
var="parameters" styleClass="tnt-main-table">
<p:column id="columnRefType" filterBy="#{parameters.beRefType}" >
<h:outputText value="#{parameters.beRefType}" />
<p:watermark forElement="parametersListForm:parameteresList:columnRefType:filter"
value="#{msgs['parameters.beRefType.label']}"/>
</p:column>
</p:dataTable>
</h:form>
Also see this
I've got the same problem, and after reading about p:watermark I've decided I don't prefer to give the full path to the filter. I've added the following snippet under the p:dataTable definition instead:
<script type="text/javascript">
$('input.ui-column-filter').attr('placeholder','#{msgs['filter_placeholder']}"');
</script>
Of course, it will enrich ALL column filters in ALL tables, but you can always append data table id to the query...

How can I use rowIndex of p:dataTable to hide/show another component?

I am trying out with p:dataTable. There I have three column. In second column I have commandbutton which when clicked, it should show inputbox on respective row in 3rd column. Inputbox on 3rd column has been set style="display:none"
MY xhtml
<h:form>
<p:dataTable var="name" value="#{model.namelist}" rowIndexVar="rowIndex">
<p:column>
<h:outputText value="#{name} -----"></h:outputText>
</p:column>
<p:column>
<p:commandButton value="click" onclick="som_#{rowIndex}.show();"></p:commandButton>
</p:column>
<p:column>
<p:inputText widgetVar="som_#{rowIndex}" style="display:none">
</p:inputText>
</p:column>
</p:dataTable>
</h:form>
I think it should work, but I dont know where I am doing mistake.
When I run your code I got error in js like som_0.show is not a function. I guess widgetVar doesn't support el. That's why your code doesn't work. But this should solve your issue:
<h:form>
<p:dataTable var="name" value="#{model.nameList}" rowIndexVar="rowIndex">
<p:column>
<h:outputText value="#{name} -----"></h:outputText>
</p:column>
<p:column>
<p:commandButton value="click" onclick="$('.som_#{rowIndex}').show();"/>
</p:column>
<p:column>
<p:inputText styleClass="som_#{rowIndex}" style="display:none"/>
</p:column>
</p:dataTable>
</h:form>
As styleClass supports el. So I did the same thing with styleClass and with a little jQuery.
Edit:
You probably need to add somewhere in your code the following line:
<h:outputScript library="primefaces" name="jquery/jquery.js" />
Edit:
Here is you dynamic widgetVar version:
<h:form>
<p:dataTable var="name" value="#{so15320268.nameList}" rowIndexVar="rowIndex" widgetVar="table">
<p:column>
<h:outputText value="#{name} -----"></h:outputText>
</p:column>
<p:column>
<p:commandButton value="click" onclick="textVar_#{rowIndex}.getJQ().show();"/>
</p:column>
<p:column>
<p:inputText styleClass="som_#{rowIndex}" widgetVar="textVar_#{rowIndex}" style="display:none"/>
</p:column>
</p:dataTable>
</h:form>
After digging into the js source of primefaces I came to know that there is no show method in PrimeFaces.widget.InputText like PrimeFaces.widget.Dialog. So you need to extract the jQuery object behind from the widgetVar and it can be done by widgetVar.getJQ() or widgetVar.jq; these two has been defined in PrimeFaces.widget.BaseWidget as:
PrimeFaces.widget.BaseWidget = Class.extend({
init: function(cfg) {
this.cfg = cfg;
this.id = cfg.id;
this.jqId = PrimeFaces.escapeClientId(this.id),
this.jq = $(this.jqId);
//remove script tag
$(this.jqId + '_s').remove();
},
//used mostly in ajax updates, reloads the widget configuration
refresh: function(cfg) {
return this.init(cfg);
},
//returns jquery object representing the main dom element related to the widget
getJQ: function(){
return this.jq;
}
});
I have strikeout my previous comment as it is wrong. widgetVar does support el. Hope it will help.

Primefaces DataTable ajax not updating any component except itself

<h:form id="form">
<p:messages />
<p:panel header="Análise">
<h:outputText value="Mês da análise: " />
<p:selectOneMenu value="#{report005.selectedMes}">
<f:selectItems var="data" value="#{report005.analiseMeses}" itemLabel="#{report005.formataDataCombo(data)}" />
<f:convertDateTime pattern="MM/yyyy" />
</p:selectOneMenu>
<p:commandButton value="Análises" update="analiseTable" actionListener="#{report005.loadAnalise()}" />
<p:dataTable id="analiseTable" var="pes" value="#{report005.analiseModel}" selection="#{report005.selectedAnalise}" emptyMessage="Não há registros...">
<p:column selectionMode="multiple" style="width:18px" />
<p:ajax event="rowSelectCheckbox" listener="#{report005.loadAnaliseProduto()}" update="produtosmanycheck" />
<p:column headerText="Código">
#{pes.cod_analise}
</p:column>
<p:column headerText="Nome">
#{pes.dsc_analise}
</p:column>
<p:column headerText="Descrição">
#{pes.dsc_resumida_acao}
</p:column>
<p:column headerText="Planejamento">
<h:outputText value="#{pes.dat_planejamento_analise}">
<f:convertDateTime pattern="dd/MM/yyyy" />
</h:outputText>
</p:column>
</p:dataTable>
</p:panel>
<p:panel header="Produto Gerencial">
<p:selectManyCheckbox id="produtosmanycheck" value="#{report005.selectedProduto}" layout="pageDirection">
<f:selectItems id="teste" value="#{report005.produtos}" />
</p:selectManyCheckbox>
</p:panel>
<p:commandButton value="Enviar" action="#{report005.send}" ajax="false" />
</h:form>
Whan the AJAX event "rowSelectCheckbox" is fired, it does not find the 'produtosmanycheck' component to update, returning the following error to me:
javax.faces.FacesException: Cannot find component with identifier
"produtosmanycheck" referenced from "form:analiseTable". at
org.primefaces.util.ComponentUtils.findClientIds(ComponentUtils.java:251)
at
org.primefaces.util.AjaxRequestBuilder.addIds(AjaxRequestBuilder.java:102)
at
org.primefaces.util.AjaxRequestBuilder.update(AjaxRequestBuilder.java:90)
I already tried= :form:produtosmanycheck, form:produtosmanycheck, :produtosmanycheck, produtosmanycheck
I tried removing the FORM id too... without success...
What am I doing wrong? I can't update any component but the DataTable...
You can reach that produtosmanycheck using :form:produtosmanycheck
EDIT: Nested forms will not work properly and give all kinds of DOM issues like the one you're experiencing. Work out a way to separate your view components into separate forms and then try the above named access.
Have you tried putting the id "produtosmanycheck" on the parent p:panel element instead of on the p:selectManyCheckbox itself?
Form nesting should never be done in JSF even with prepend ID false as it will cause unexpected or no behaviour.
I will post my own answer (in the end I came up with nested forms idea) as well as voting up #kolossus because he was basically right and couldn't know about nested forms.
Nested forms aren't the "thing" of JSF only (as it may seem from #JordanDenison answer), it is a general rule of HTML --> nesting forms is forbidden in HTML !
You may want to read this nesting forms in HTML

multiple h:forms in ui:repeat

I'm trying to have multiple h:forms on a page which are rendered with a ui:repeat component. If I have only one generated h:form, everything works perfect. If I have multiple h:forms, only the latest h:form will work! (If I try to submit another form then the last, only null is passed trough my service!)
<ui:repeat var="element" value="#{myService.elementList}">
<rich:simpleTogglePanel switchType="client"
label="#{element.codeElement} - #{element.description}"
opened="#{myService.isUiSelected(element)}"
onexpand="expand#{element.codeElement}()"
oncollapse="collapse#{element.codeElement}()">
<h:form id="newKindForm">
<a:commandLink ajaxSingle="true" id="idLink" onclick="#{rich:component('newTargetPanel')}.show()">
<a:commandButton id="myButton"
value="new Form"
action="#{myService.newForm(element)}"/>
</a:commandLink>
</h:form>
<rich:modalPanel id="newTargetPanel" autosized="true" width="450">
<f:facet name="header">
<h:outputText value="My Pannel Title" />
</f:facet>
<f:facet name="controls">
<h:panelGroup>
<h:graphicImage value="/img/close.png"
id="hidelink"
styleClass="hidelink" />
<rich:componentControl for="newTargetPanel"
attachTo="hidelink"
operation="hide"
event="onclick" />
</h:panelGroup>
</f:facet>
<!-- THIS IS THE PROBLEMATIC FORM -->
<h:form>
<a:include viewId="../myRepeatableForm.xhtml" />
</h:form>
</rich:modalPanel>
</ui:repeat>
Some suggestion?
Thank You
you can contain everything in a single form, and use execute attribute to submit only the elements you want. like this:
<h:form id="newKindForm" prependId="false">
<ui:repeat id="newKindRepeat" var="element"
value="#{myService.elementList}" varStatus="varStatus">
<h:panelGroup id="newKindPanel">
<a:commandButton id="myButton"
execute="newKindRepeat:#{varStatus.index}:newKindPanel"
onclick="#{rich:component('newTargetPanel')}.show()"
value="new Form"
action="#{myService.newForm(element)}"/>
</h:panelGroup>
</ui:repeat>
</h:form>
please notice prependId of h:form, id and varStatus of ui:repeat, execute of a:commandButton.
btw, supposing that a: stands for ajax4jsf, i wouldn't recommend using commandButton nested in commandLink.
Is #{myService.elementList} a List ? If so, I'm not sure if that will work. Try using javax.faces.model.DataModel instead. Be sure to read the documentation carefully. It works something like this:
public Datamodel getElements(){
if(elements == null)
elements = new ListDataModel(getElementList());
return elements;
}
public List<Element> getElementList(){
elementList = foo(); // load the elements in your List like you did before
return elementList;
}
in your view: <ui:repeat var="element" value="#{myService.elements}">
I'm not familiar with RichFaces, this is the only suggestion I can make.

Resources