0

I'm working on a JSF 2.2 application and wish to change radio buttons with JavaScript. I'm getting the latitude and longitude using HTML5 geolocation in JavaScript and wish to pass these to an xhtml page wired to a Java bean so that when it is submitted, it is sent to the Java code on the server for processing.

Geolocation gets the latitude and longitude in degrees and fractions of a degree, which I convert to degrees, minutes and seconds, then pass the values to input fields in JavaScript using code such as:

document.getElementById("lat-deg").value = latDeg;

which inserts the degrees of latitude in the xhtml code as

<h:inputText class="coord" id="lat-deg"
    validatorMessage="Error: Degrees of latitude must be a number between 0 and 90"
    value="#{solarPower.latDeg}">
    <f:validateRegex pattern="[0-9]+" />
    <f:validateLongRange minimum="0" maximum="90" />
</h:inputText>

and likewise for minutes and seconds of latitude, and degrees, minutes and seconds of longitude. This works perfectly OK when a button is clicked to invoke the JavaScript code.

However, I want to use radio buttons for negative latitudes (south) and negative longitudes (west), but after many attempts I'm unable to get this to work.

In my JavaScript code I have the following:

var lat = position.coords.latitude;
var latMinus = false;
if (lat < 0) latMinus = true;
lat = Math.abs(lat);
var latDeg = Math.floor(lat);
// Get also latMin and latSec, then update the <h:inputText ...> fields
if (latMinus) {
  document.getElementById("south").checked = true;
} else {
  document.getElementById("north").checked = true; // <===
}

The code fails at the line indicated with the Firefox console displaying the message:

TypeError: document.getElementById(...) is null

when it attempts to set the radio button to "N". In the southern hemisphere it would fail at the previous document.get... statement.

The corresponding xhtml code is:

<h:selectOneRadio id="lat-radio" value="#{solarPower.latNS}">
    <f:selectItem id="north" itemValue="N" itemLabel="N" />
    <f:selectItem id="south" itemValue="S" itemLabel="S" />
</h:selectOneRadio>

This is repeated for longitude.

I tried replacing the JavaScript code above with this:

if (latMinus) {
    document.getElementById("lat-radio").itemValue = "S";
} else {
    document.getElementById("lat-radio").itemValue = "N";
}

but it still fails, but this time nothing is printed in the console.

In looking at the html source as seen by the browser the following code was generated by JSF

<td>
<input type="radio" checked="checked" name="lat-radio" id="lat-radio:0" value="N" /><label for="lat-radio:0"> N</label></td>
<td>
<input type="radio" name="lat-radio" id="lat-radio:1" value="S" /><label for="lat-radio:1"> S</label></td>

where obviously it's changed the id="lat-radio" to "lat-radio:0" and "lat-radio:1", which might have something to do with the problems I'm having. Finally, I also tried accessing the ids "north" and "south" in the JavaScript code, but with no success.

So far it hasn't been easy to find much online on how to change JSF radio buttons with JavaScript, and would most appreciate some help in getting this problem resolved - many thanks in advance.

csharp
  • 464
  • 2
  • 10
  • 19
  • Hi, they are not 'jsf radio buttons' but client-side plain html ones. So like you see in the answer by @Selaron, it is 'identical' to what is done in https://stackoverflow.com/questions/21166860/check-a-radio-button-with-javascript – Kukeltje Oct 18 '18 at 09:46

2 Answers2

1

You'd put your input components into a form if you want to be able to submit input values:

<h:form id="frmGeo">
    <h:panelGroup id="radioNorthVsSouth">
        <h:selectOneRadio id="lat-radio">
            <f:selectItem itemValue="N" itemLabel="N" />
            <f:selectItem itemValue="S" itemLabel="S" />
        </h:selectOneRadio>
    </h:panelGroup>
</h:form>

And client side it is all plain html and selecting a 'jsf radio button' is done like selecting a radio button in plain html. So in this case, you can adjust the inputs like this:

if (latMinus) {
    document.getElementById('frmGeo:radioNorthVsSouth')
        .querySelectorAll('input[value=S]')[0].checked=true;
} else {
    document.getElementById('frmGeo:radioNorthVsSouth')
        .querySelectorAll('input[value=N]')[0].checked=true;
}

or this less verbose but also less expressive one:

if (latMinus) {
    document.getElementById('frmGeo:lat-radio:1').checked=true;
} else {
    document.getElementById('frmGeo:lat-radio:0').checked=true;
}
Kukeltje
  • 12,223
  • 4
  • 24
  • 47
Selaron
  • 6,105
  • 4
  • 31
  • 39
-2

Many thanks - I got the less verbose version to work, but not the more detailed version. I already had the xhtml code inside a form, but found that the h:panelGroup tag to be redundant.

Here is my xhtml code:

<h:form id="index-form" prependId="false">
  <!-- Other code -->
  <h:selectOneRadio id="lat-radio" value="#{solarPower.latNS}">
    <f:selectItem itemValue="N" itemLabel="N" />
    <f:selectItem itemValue="S" itemLabel="S" />
  </h:selectOneRadio>
  <!-- Other code including the equivalent for longitude -->
</h:form>

and the relevant part of my JavaScript code is as follows:

if (latMinus) {
    document.getElementById("lat-radio:1").checked=true;
} else {
    document.getElementById("lat-radio:0").checked=true;
}

and likewise for longitude.

Note that there is no need to prefix the id by "index-form:" in my case because I've added the prependId="false" attribute in the h:form tage.

csharp
  • 464
  • 2
  • 10
  • 19
  • 1
    Please accept the other answer, since it helped. And regarding prependId, bad choice, see https://stackoverflow.com/questions/7415230/uiform-with-prependid-false-breaks-fajax-render – Kukeltje Oct 19 '18 at 15:21