Princess Cornflakes

Too trashy to print on a cereal box

Archive for September 2008

Use rowKeyVar to Access dynamic id from JSF dataTable using JavaScript

with 6 comments

In JSF, ids of dataTable rows are dynamically generated. This can be frustrating when trying to access a specific field in a specific row from JavaScript. The trick to getting the specific dataTable field is to know the exact row number in JavaScript, and that is what I will demonstrate here.

I am using RichFaces 3.1.6 along with Apache MyFaces 1.1.3. For unexplicable reasons, I cannot get MyFaces 1.2.x to run with my Websphere Application Server Community Edition v. 2. So I’m stuck with 1.1.x. What this means is that I can’t use the newest version of RichFaces and I’m stuck with a lot of components that don’t work right.

I have a <rich:dataTable> with many rows, each of which contains several columns with <h:inputText> fields. A time value goes into each field and I need to validate the time input strings and compare them to one another.

I tried to use <f:validator>. Well it worked ok, but I couldn’t modify the javascript event that controlled the validation. It only responded to the “enter” key being pressed, and I wanted “onblur” to trigger the validation. Therefore I made a simple javascript call from within the <h:inputText> tag, like this:

<h:inputText value="#{addShopScheduleBean.sundayp2}" size="5"
id="sunp2" onblur="validateTime(this.value);">

I used ValidateTime like this, to validate a well-formed time string:

function validateTime(html) {
var match = /^([0-1]?[0-9]|2[0-3])\:[0-5][0-9]$/.test(html);
// empty string is ok
if ((!match) && (html.length > 0)) {
alert("BAD VALUE! ");

But, I need validateTime to do more. I need it to compare that field with another field in the same row.

JSF creates dynamic ids for all components, and the two id’s I needed were roughly:



The 0 refers to the row number. If I needed components from row 23 it would be:



It is this row number variable I needed JavaScript to have access to. Here is how I solved the problem.

I used the rowKeyVar in <rich:dataTable> like this:

<rich:dataTable headerClass="schedule" footerClass="schedule-foot"
styleClass="schedule" value="#{addShopScheduleBean.employees}"
var="schedshopemp" id="dt-173" rowKeyVar="myrow">

then, in my inputText, I called my javascript function, validateTime, using “myrow” as an argument:

<h:inputText value="#{addShopScheduleBean.sundayp2}" size="5"
id="sunp2" onblur="validateTime(this.value,#{myrow});">

Voila! My JavaScript can now see the row number from which it is getting called and I can get to the value of other inputTexts in that row, like this:

function validateLast(html, row) {
var lastval = document.getElementById('a4jform-3:dt-173:'+ row +':sunp1').value;
alert("html is " + html + " and row is " + row + " and lastval is " + lastval);

That enabled me to see what was in the ‘a4jform-3:dt-173:5:sunp1’. If for example I was in ‘a4jform-3:dt-173:5:sunp2’. Now I can compare the two entered times to see if the last one is earlier than the first and produce the appropriate errors for the user.

I hope this has helped someone.

Written by nattie

September 18, 2008 at 1:49 pm