Avoid onRowClick event when outputLink is clicked inside of RichFaces datatable - javascript

How to avoid the call to onRowClick on the datatable on the column that has the outputlink (target to a new window)?
<rich:dataTable id="dt" value="#{bean.cars} var="_car">
<a:support event="onRowClick" action="#{action.navigateToCarDetails(_car.id)}"/>
<rich:column>
<f:facet name="header">Select</f:facet>
<a:commandLink onclick="Event.stop(event)" action="#{bean.toggleSelectedCar(_car.id)}" reRender="dt" ajaxSingle="true" limitToList="true">
<h:graphicImage value="/img/icon_checkbox_#{bean.isCarSelected(_car.id) ? 'active' : 'inactive'}.gif"/>
</a:commandLink>
</rich:column>
<rich:column>
<f:facet name="header">Brand</f:facet>
<h:outputLink value="#{_car.link}" target="_blank">
<h:outputText value="#{_car.brand}"/>
</h:outputLink>
</rich:column>
<rich:column>
<f:facet name="header">Year</f:facet>
<h:outputText value="#{_car.year}"/>
</rich:column>
<rich:column>
<f:facet name="header">Color</f:facet>
<h:outputText value="#{_car.color}"/>
</rich:column>
</rich:dataTable>
So with the sample above, when I click on the row, it will navigate to a page with the detail of the Car.
And when clicked on the Select column's row, it will update the selected car, and update the checkbox icon accordingly, but without navigate to the car detail page, because I have the onclick="Event.stop(event)".
But when I click on the outputLink box, other than opening a new window and show the manufacturer web page, it also update the original page to the car details. How do I prevent this from happening? (I tried adding the onclick event stop just like the select column, but other than stopping the onrowclick event, it also block the link to the manufacturer web page)

Basically what Event.stop(event) does is the following:
\\ stops the event from bubbling up the event chain
event.stopPropagation();
\\ prevents the default action the browser makes on that event
event.preventDefault();
In your case you want just to prevent bubbling, so a way to go:
onclick="event.stopPropagation()"

You should be able to do something like this:
<rich:dataTable
onRowClick="if (event.target.id.endsWith('columnId')) return false;" …>
the onRowClick function is executed before the a4j:support so if you return false the action won't be called.

Related

Check if a datatable is empty in primefaces

I have a datatable in primefaces with jsf and I need to check when the datatable is empty with jquery/js, but I have just found tags for "normal" datatables that don't work on PF.
Bean
private ArrayList<Curso> curs = null;
private ArrayList<Curso> listado_filtrado;
private DefaultStreamedContent informe_cursos;
Html
<p:outputPanel id="opTabla" >
<p:dataTable id="tabla_elements"
value="#{Cursos.curs}"
var="element"
filteredValue="#{Cursos.listado_filtrado}"
emptyMessage="No se encontraron elementos"
paginator="true" rows="20"
currentPageReportTemplate="{startRecord} a {endRecord} de {totalRecords}"
paginatorTemplate="{FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
paginatorPosition="bottom">
<p:ajax event="filter" update="exportar"/>
<f:facet name="header">
<div class="header-field-col">
<p:commandButton id="anadir_curso" value="Añadir curso nuevo" icon="ui-icon-plus" />
</div>
<div class="header-field-col">
<p:commandButton id="exportar" value="Exportar" ajax="false" disabled="#{empty Cursos.curs}"
icon="ui-icon-arrowreturnthick-1-s">
<p:fileDownload value="#{Cursos.informeCursos}" />
</p:commandButton>
</div>
</f:facet>
Your p:dataTable most likely references a list. Add an ajax event handler to it for e.g. the filter (all the ones that can make a page empty)
<p:dataTable value="#{myBean.myList}"...>
<p:ajax event="filter" update="exportButton" ... >
...
</p:dataTable>
use a p:commandButton with a disabled attribute like this:
<p:commandButton id="exportButton" value="export" disabled="#{empty myBean.myList}" ... />
It disables the commandButton client and serverside if the list is empty. So users cannot hack it client-side either.
The 'update' element in the commandButton makes sure the button state is, well,... updated on the relevant events. This is all rather basic ajax stuff, maybe read some tutorial on that

Primefaces doesn't recognize the value of the cell/field if I don't leave the cell/field.

I'm having this issue with saving data from the grid in PrimeFaces. When I set the value in the cell, and then change another and another cell, click here and there, and then I click on the save button, everything is working perfect. But if I miss to exit the cell (to change the focus), and just click the save button, the value from that last cell is lost.
Here is my cell:
<p:cellEditor>
<f:facet name="output"><h:outputText style="text-transform: uppercase" value="#{bBean.someData}" /></f:facet>
<f:facet name="input">
<p:inputText style="text-transform: uppercase" value="#{bBean.someData}" label="Some data">
</p:inputText>
</f:facet>
</p:cellEditor>
It looks like PrimeFaces is not able to recognize the change if some event is not fired.
Any ideas?
Giving your <p:inputText> onmouseout event you can additionally save value when user leaves cell with mouse pointer:
<p:ajax event="mouseout" process="#this" partialSubmit="true"/>
Ok, now I fixed it for sure :)
I created a hidden button:
<p:commandButton process="#this" style="display:none !important" id="btn" value="SB"/>
and a javascript function that will simulate clicks on the hidden button:
function takefocus(){
$(PrimeFaces.escapeClientId('form:btn')).click();
}
and I added to the save button, before calling save:
<p:commandButton value="Save" onclick="takefocus();PF('waitDialog').show();saveData();"/>
and it is working fine.
The following works for Firefox, but not for Chrome.
So if you find a better solution please share it here.
<p:inputText onblur="triggerChange(this)... />
function triggerChange(el) {
var e = jQuery.Event('keydown');
e.which = 13;
e.keyCode = 13;
$(el).trigger(e);
}

Datatables row id in JavaScript

I would like to get the id of datatables row to call click() on a hidden button in the same table cell.
It is done that way because all buttons have to look like h:commandButton and i couldn't force p:commandButton look like them. And h:commandbutton doesn't have oncomplete event. I know I could use DataModel, but is there another way to do it (using JS, JQuery)?
When i put hardoced id (p:table:4:hiddenButton) everything is ok, but how to get that row number for each cell??
<h:form id="p">
<h:dataTable value="#{bean.paymentList}" var="pmt" id="table" >
...
<h:column>
<f:facet name="header">
<h:outputText value="#{bundle.action}" />
</f:facet>
<h:commandButton type="button" value="#{bundle.approve}"
onclick="document.getElementById('p:table:??:hiddenButton').click();" />
<p:commandButton id="hiddenButton" value="hidden" style="display: none;"
oncomplete="if (#{pmt.errorsNum} > 0) {
return confErrDial.show();
} else {
return confDial.show();};">
<f:setPropertyActionListener value="#{pmt.id}" target="#{bean.holder}" />
</p:commandButton>
</h:column>
</h:dataTable>
</h:form>
EDIT:
Ok i did some trick using JQuery, it may be not nice but works.
What I did:
I added id to h:commandButton and on onclick event i get id of h:commandButton and replace its id with id of hidden p:commandbutton, so its code is now:
<h:commandButton id="button" type="button" value="#{bundle.approve}"
onclick="document.getElementById(($(this).attr('id')).replace('button','hiddenButton')).click();"
Still maybe someone knows better solution.
PS: It is strange because $(this).parent().attr('id') is null. I think it has something with that no element is created with id p:table:0 p:table:1 etc...

JSF Primefaces set button enabled when table row is selected

I have a list of users in a table and with disabled Delete button. I need to enable the Delete button when I select the row in the table. How can I do this?
<p:dataTable value="#{userBean.patients}" var="item"
selectionMode="single" rowKey="#{item.id}"
selection="#{userBean.selected}"
onRowSelected="deleteButton.disabled='false';"> // HOW TO WRITE THIS EVENT CORRECTLY?????
// columns
</p:dataTable>
//This button must be enable after I click on any table row
<p:commandButton id="deleteButton" value="Delete" disabled="true" />
Maybe, I need to use onRowClick event. I dont know the name of this event
Thanks for jsfviky71 !
I write:
<h:form id="form">
<p:dataTable value="#{bean.patients}" var="item"
selectionMode="single" rowKey="#{item.id}"
selection="#{bean.selected}" >
<p:ajax event="rowSelect" update=":form:deleteButton" listener="#{bean.onRowSelect}" />
// data in rows
</p:dataTable>
<p:commandButton id="deleteButton" value="Delete" disabled="#{bean.disabled}"/>
And in my bean:
private Boolean disabled = true;
// getter and setter
public void onRowSelect(SelectEvent event) {
disabled = false;
}
Hope this will help to others
One solution could be using
<p:ajax event="rowSelect" update=":deleteButton" listener="#{bean.someListener}" />
inside datatable.
This catches the row selection event, calls a listener and updates the button.
Now you could define the listener in the backing bean that just updates the value of a boolean instance variable, that reflects the disabled/enabled status of the button in the view:
<p:commandButton id="deleteButton" value="Delete" disabled="#{bean.selectedBoolean}" />
You can take a look at primefaces showcase for a similar scenario:
http://www.primefaces.org/showcase/ui/datatableRowSelectionInstant.jsf
Hope this helps.

Ajax + JSF 2 times clicking after the first click

I have a dataTable with a column named DELETE (it is a link) which has an listener . When I click it the first time (click 1) it deletes the row (as expected), but when I try it with another row after that nothing happened (click 2). In fact wherever I click next nothing happen. I should click another time (click 3) to get it work. I don't want that.
Attention: The "delete()" method in my_user is not reached after "click 2".
Here is the code for the column:
<h:column>
<f:facet name="header">#{lng.del}</f:facet>
<h:form>
<h:commandLink action="#">
<f:ajax event="click" listener="#{my_user.delete}" render="#all" />
<h:graphicImage name="delete.png" library="images" styleClass="tableIcon" />
</h:commandLink>
</h:form>
</h:column>
You've multiple forms inside the table. When you re-render another form from inside a form by ajax, then its view state will get lost and hence the 1st click will fail. This click however takes care that the form gets the view state back, so the 2nd click works.
Technically you need to re-render only the content of the other form, but this isn't possible in this particular use case. Better put the <h:form> outside the <h:dataTable> so that you have a single form with a shared view state.
<h:form>
<h:dataTable>
...
</h:dataTable>
</h:form>
If your page contains another forms as well, I'd suggest to render only the current form instead of all, otherwise any actions on those forms will fail as well.
<f:ajax event="click" listener="#{my_user.delete}" render="#form" />

Categories

Resources