Stop generation tables and fieldset tag in output of Check box / Radio button Group control - xpages

When using a checkbox group XPage generates fieldset and table tags around it. Is there a way to not generate that? For e.g. if my XPage source looks like this -
<xp:checkBoxGroup id="checkBoxGroup" disableTheme="true" value="#{document1.CheckboxGroup}">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:new Array("Option 1", "Option 2", "Option 3");}]]></xp:this.value>
</xp:selectItems>
</xp:checkBoxGroup>
Then my generated code is
<fieldset id="view:_id1:checkBoxGroup">
<table>
<tr>
<td>
<label><input name="view:_id1:checkBoxGroup" value="Option 1" type="checkbox"> Option 1</input></label>
</td>
<td>
<label><input name="view:_id1:checkBoxGroup" value="Option 2" type="checkbox"> Option 2</input></label>
</td>
<td>
<label><input name="view:_id1:checkBoxGroup" value="Option 3" type="checkbox"> Option 3</input></label>
</td>
</tr>
</table>
</fieldset>
That's a lot of code for three checkboxes. And it messes up my CSS as putting any CSS for table tag puts it on the checkbox group also. The also goes for radio button group. I tried setting disableTheme property to true but that also didn't work.

If you want to fundamentally change the structure of the HTML representation of a component, you can use the Extensibility API to create an alternate renderer. This allows you full control over what markup is sent to the browser for a specific component instance without changing how any other components are rendered. Register the renderer with the same component-family as the default renderer (javax.faces.SelectMany), but assign it a custom renderer-type; if you then assign that custom value to the rendererType property of a specific checkbox group, Domino will use your custom renderer class to emit the HTML instead of the default renderer class.

You can also use the xp:radio control instead of the xp:radioGroup control and then group several radio buttons using the groupName property. Radio buttons rendered from xp:radio are not surrounded with fieldset and table.

Related

JSF datatable not complying to WCAG due to unsupported aria-label attribute

I am using JSF to code my application and it has a datatable.
Each row of the datatable has a checkbox in the first column, and some text in the rest of the columns.
My application needs to comply to the WCAG 2.0 and I'm using a Chrome Extension "Axe" to scan my application.
The "Axe" tool flagged out that the datatable with the checkboxes is not complying to the clause "Ensure every form element has a label" and the proposed solution is to add the "aria-label" attribute.
However JSF datatable does not have the "aria-label" attribute.
Would need to ask if any experts out there have any solution?
JSF 2.2 Support pass through attributes. So it's easy to add customized attributes into the primefaces tag.
Add tag reference at the top:
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
Declare it inside the primefaces tag:
p:inputText value="#{bean.value}" pt:aria-label="Whatever you want"
A checkbox needs a label, whether visible or not, in order for screen readers to announce the checkbox properly. For sighted users, having a column header in your table is sufficient as the label for the checkboxes below it. However, for screen reader users, unless you associate the column header with each checkbox, it won't be announced. Ignoring JSF for a moment, if you are writing straight html, you could have something like this:
<table border="1" style="border-collapse: collapse">
<tr>
<th scope="col" id="check_label">select me</th>
<th scope="col">some other value</th>
</tr>
<tr>
<td>
<input type="checkbox" aria-labelledby="check_label">
</td>
<td>hello</td>
</tr>
<tr>
<td>
<input type="checkbox" aria-labelledby="check_label">
</td>
<td>there</td>
</tr>
</table>
Each checkbox has an aria-labelledby attribute pointing to the column header ("check_label"). This works pretty well for most screen readers, but there are some cases where the checkbox label is not read, for example in NVDA if you are using the table navigation keys (ctrl+alt+arrow) and navigate down the checkbox column, the name is not read for the checkboxes. That could be a bug with NVDA, I'm not sure.
An alternative to the above is to have a visually hidden <label> specifically associated with each checkbox. This works whether you navigate the table using the TAB key or ctrl+alt+arrow.
<table border="1" style="border-collapse: collapse">
<tr>
<th scope="col">select me</th>
<th scope="col">some other value</th>
</tr>
<tr>
<td>
<input type="checkbox" id="check1">
<label for="check1" class="sr-only">select me</span>
</td>
<td>hello</td>
</tr>
<tr>
<td>
<input type="checkbox" id="check2">
<label for="check2" class="sr-only">select me</span>
</td>
<td>there</td>
</tr>
</table>
Now, getting back to JSF, of which I knew nothing about until I read this question, it looks like there are two ways to specify a checkbox, https://docs.oracle.com/javaee/5/tutorial/doc/bnaqd.html#bnaqh.
selectBooleanCheckbox
selectManyCheckbox
selectBooleanCheckbox, by default, does not have a label associated with the checkbox where as selectManyCheckbox does. However, you can also specify an <h:outputLabel> to be paired with the selectBooleanCheckbox so I think that's your answer. See the example in the selectBooleanCheckbox doc.
And with more recent versions of JSF you can also add the aria related attributes by using JSF Passtrough attributes (Spec)
So provided you add the right namespacedeclaration, you can do
<h:selectBooleanCheckbox pt:aria-labbeledby="check_label" ...>
But it can also be put on a datatable
<h:datatable pt:aria-labbeledby="check_label" ...>

Add space between the radio button and lable in h:selectOneRadio and f:selectItems

I am using jsf2 with primefaces.
h:selectOneRadio
f:selectItems
h:selectOneRadio
This produces a radio button and the input label inside the same td such as
<td>
<input type=radio> </input>
label
</td>
My problem is I need to add space between the radio button and the label.
(X)C121 Active
(X)LRM
In the above radio button list I need to add space such as
(x) <---Space--> C121 Active
(x) <--Space --> LRM
What is the best way I can add space for this ? Need help. Sorry as I am new for JSF I could not figure-out a solution.
P.S (x) represents a radio button
Tech Stack : JSF 2.0, Spring 3.x , Hibernate 4.x.
I think some styling like this would be appropriate:
input[type=radio]{
margin-right: 7px;
}
Put it in <style>-tag in h:head or better yet in an external css-file you include with h:outputStylesheet.
This way, you'll target them all without further code.

Access JSF Custom Tag's id

TL;DR
Is there something like composite's cc.clientId that will give me the id of a custom tag?
Details:
I'd like a custom tag that will render a label, a value, and an icon. When the icon is clicked, a Bootstrap modal is supposed to open up that will edit the value.
<ui:composition>
<div> #{field.label}: #{field.value}
<a class="icon-pencil" data-target="#editForm" data-toggle="modal">
</div>
<h:form id="editForm" class="modal hide fade" role="dialog" ...>
... there's an input here linked to field.value ...
</h:form>
</ui:composition>
I can use the tag with <my:editor />. When I do so within a ui:repeat, an id is prepended to the editForm so that it renders with id j_idt104:editForm. So I need to modify the data-target to include the id.
This would be really easy with a composite component because I have access to the id via cc.clientId:
data-target="\##{cc.clientId}\:editForm"
However, I can't get it to work with a custom tag because I don't know of an EL expression (or something) that will give me access to the id. I could probably wait until after the page is loaded, then use jQuery to inspect the id and set the data-target after the fact, but I was hoping for a more pure-JSF solution.
I'm using JSF 2.1 and Bootstrap 2.3, at the moment.
Answer seems to be no. BalusC says you should replace things like custom tags with "normal" JSF components. In this case, that would mean using the composite component.
If you're deadset on using custom tag, I worked around the issue (with lots of help from the answer here) by using an index in the form's id:
I replaced the ui:repeat with a c:forEach that has access to the item's index:
<table>
<c:forEach items="#{bean.items}" var="item" varStatus="status">
<my:editor index="#{status.index}" ... />
</c:forEach>
</table>
And in the custom tag, I used the index in the data-target:
<tr>
<td>#{label}: #{value}</td>
<td>
<a data-target="\#editForm-#{index}" ... ></a>
<h:form id="editForm-#{index}" ... >
...
</h:form>
</td>
</tr>
The only catch is that c:forEach is a build-time construct (see details in this answer), which is a problem if you need any render-time data (like if you build information up in preRenderView). If you do, then you're better off using ui:repeat with a custom component, and relying on the cc.clientId.

p:selectOneButton suddenly stops working, first button is not clickable anymore

I have been successfully been using the PrimeFaces selectOneButton - using PF 3.5.
Suddenly, it has stopped working, and the first button is always not clickable - there has been no changes to the webpage code nor the backing bean code (which would affect it).
<p:selectOneButton value="#{bean.result}">
<f:selectItems value="#{bean.options}" />
<p:ajax event="change" process="popupPanel"
update="Grid"
listener="#{myBackingBean.submitItem(bean.itemId)}" />
</p:selectOneButton>
I have a theory to why the first button is not clickable.
From PrimeFaces SelectOneButton showcase:
SelectOneButton is an input component to select options using regular buttons instead of radio buttons
So, SelectOneButton is really radio buttons, but displayed with a nice touch ;)
Now, the rendered HTML of selectOneButton with two options is as follows;
<div class="ui-button ui-widget ui-state-default ui-button-text-only ui-corner-left ui-state-active">
<input id="mainForm:Grid:0:j_idt64:0" name="mainForm:Grid:0:j_idt64" type="radio" value="Yes" class="ui-helper-hidden" checked="checked">
<span class="ui-button-text ui-c">Yes</span>
</div>
<div class="ui-button ui-widget ui-state-default ui-button-text-only ui-corner-right">
<input id="mainForm:Grid:0:j_idt64:1" name="mainForm:Grid:0:j_idt64" type="radio" value="No" class="ui-helper-hidden">
<span class="ui-button-text ui-c">No</span>
</div>
I notice two differences...
1) The div classes are different.
2) First option has checked="checked"
1) Checking the CSS of the div class, I cannot see anything major to which would make the button unclickable.
2) Obviously, since its really a radio button, the first option is "checked".
Now, when clicking a plain-old-standard radio button, you can't click on it to "release it" - once its clicked its clicked, and other radio buttons need to be clicked to change the option.
Since my first option is always "checked" would this block the button to be "clickable"? Has any one else ever experienced something similar? Having looked around I seem to be the only one who has had this issue.
I can do workarounds, but I can not find out why it has suddenly stopped working, and would rather find a solution!
Any help is appreciated!
UPDATE
Luckily, I found an old previous version of my webapp and I checked the rendered HTML.
Heres the following HTML of the first button (which is unclickable on my current version).
<div class="ui-button ui-widget ui-state-default ui-button-text-only ui-corner-left">
<input id="mainForm:Grid:0:j_idt63:0" name="mainForm:Grid:0:j_idt63" type="radio" value="Yes" class="ui-helper-hidden">
<span class="ui-button-text ui-c">Yes</span>
</div>
The two differences I described above, are not rendered in my previous version - there is no "ui-state-active" in the div class, nor "checked='checked'" in my <input />
I edited the HTML manually on my current (unclickable) version, and removed "checked='checked'" - this had no effect. I then removed the "ui-state-active" from my div class - and the button is now clickable.
I am still puzzled to why the HTML is now rendered differently, what could I of changed which would make this happen?
Thanks again.
After many hours, I finally figured out why...
As I said in my question,
SelectOneButton is an input component to select options using regular
buttons instead of radio buttons
SelectOneButtons are radio buttons.
In the same webpage, I also use radio buttons as on option using pretty similar code...
<p:selectOneRadio value="#{bean.result}">
<f:selectItems value="#{bean.options}" />
</p:selectOneRadio>
Now, I had trouble that when the user was presented with these radio buttons, none were selected. This allowed the user to return null. Now, I didn't want the user to be able to return null, hence the need for radio buttons - one or the other. So, I set #{bean.result} to the first element in #{bean.options} before the page is rendered, so when the user is presented with the buttons, the first is selected by default.
Hence, when the selectOneButton's were rendered, the first "button" was selected, and you couldn't press it.

How to read the value of the radio button

I would like to read the selected role information on form submit (a role is selected for a user from a list of roles). How do I read the selected radio button value in my EntityHome interface (Note: I didn't want to use the h:selectOneRadio option here)
<tr>
<s:div rendered="#{userHome.instance.type ne 'admin'}">
<th width="150" class="rich-table-subheadercell center">#{_user.getName()}</th>
</s:div>
<c:forEach items="#{userHome.instance.roles}" var="_role">
<td width="150" class="center" style="background: rgb(100, 100, 100) none repeat scroll 0% 0%;">
#{_role.name}
<input type="radio" style="display : none" name="#{userHome.instance.id}" value="#{_role.id}"/>
</td>
</c:forEach>
</tr>
Two comments.
First of all. Use JSF Components where you can.
Secondly. Avoid using JSTL tags. Remove the c:forEach if you don't have to use it. Replace it with ui:repeat, h:dataTable etc.
Now to answer your question for a workaround if you can't directly use h:selectOneRadio
What you will have to do is use #WebRemote in Seam, and then by using javascript you can on form submit, set the value through Ajax in your UserHome component.
Take a look at chapter 5. Remoting in the Seam Documentation for more information on how to use Remoting.
You need to point the value / list to an ArrayList of SelectItem there's where the items you selected will be stored.

Resources