What is label's 'for' id for selectBooleanCheckbox - jsf

How to reference each individual checkbox in the outputLabel so that when I click on item's label, it would effectively be the same as if I clicked on the checkbox?
<rich:dataGrid value="#{all}" var="item" columns="3">
<h:outputLabel value="#{item.name}" for="what_here?" />
<h:selectBooleanCheckbox value="#{item.selectedForLaterUse}" id="item#{item.id}" />
</rich:dataGrid>
A possibility that comes first to mind is of course
for="item#{item.id}"
but since jsf id's are relative, it would not work, right?
There is also one option to use selectManyCheckbox but that doesn't seem to give an option to use columns.

You do not need to do it. JSF does it for you. Just specify a fixed ID as long as it's in the same scope.
<rich:dataGrid value="#{all}" var="item" columns="3">
<h:outputLabel value="#{item.name}" for="item" />
<h:selectBooleanCheckbox value="#{item.selectedForLaterUse}" id="item" />
</rich:dataGrid>
JSF will generate the proper HTML accordingly. Open page in browser, rightclick and do View Source to see it yourself. The generated HTML element IDs are in this particular case composed of all parent NamingContainer components and the current item index.
Here's an example of the generated output, assuming that you're giving all NamingContainer components a fixed ID like <h:form id="form"> and <rich:dataGrid id="grid"> (otherwise JSF will autogenerate IDs like j_idt1 and so on, which would work perfectly fine as well but is not immediately readable):
<table id="form:grid" class="rf-dg">
<tbody id="form:grid:dgb" class="rf-dg-body">
<tr class="rf-dg-r">
<td class="rf-dg-c">
<label for="form:grid:0:item">one</label>
<input id="form:grid:0:item" type="checkbox" name="form:grid:0:item" />
</td>
<td class="rf-dg-c">
<label for="form:grid:1:item">two</label>
<input id="form:grid:1:item" type="checkbox" name="form:grid:1:item" />
</td>
<td class="rf-dg-c">
<label for="form:grid:2:item">three</label>
<input id="form:grid:2:item" type="checkbox" name="form:grid:2:item" />
</td>
</tr>
</tbody>
</table>

Related

SelectOneMenu and valueChangeListener error when set disabled attribute

I am working with a <h:selectOneMenu> component. It has the disabled attribute set. Due to this I am unable to use a valueChangeListener on the component. I tried using the <a4j:actionListener> tag, but I get an error saying the parent tag is not of type ActionSource. Is there any other way of triggering an action when the selected value changes?
Here's the tag:
<table>
<tr>
<td><input type="radio" id="auto" name="name" value="auto" onclick="onclickfunction (this);"> </input>
</td>
<td>
<h:selectOneMenu id="abc" value="#{bean.val}" disabled="true">
<f:selectItem itemLabel="Select ..." itemValue=""/>
<f:selectItems id="list" value="#{bean.list}"/>
<a4j:ajax event="change" execute="#this" limitRender="true"
listener="#{bean.listener}" render="other" />
</h:selectOneMenu>
</td>
</tr>
<tr>
<td><input type="radio" id="manual" name="name" value="manual" onclick="onclickfunction (this);"> </input>
</td>
<td>
<h:selectOneMenu id="xyz" value="#{bean.val}" disabled="true">
<f:selectItem itemLabel="Select ..." itemValue=""/>
<f:selectItems id="list" value="#{bean.list}"/>
<a4j:ajax event="change" execute="#this" limitRender="true"
listener="#{bean.listener}" render="other" />
</h:selectOneMenu>
</td>
</tr>
</table>
The tag starts out with disabled set to to true. The disabled attribute is changed via javascript.I had to do this via javascript due to a design choice I made. This select tag is one of two tags that the user can toggle using a radio button. I couldn't use the JSF radiobutton tag as it requires an f:selectitem child tag. I just need a radio button for toggling between 2 select tags.
Let the disabled attribute evaluate true only during render response.
<h:selectOneMenu ... disabled="#{facesContext.renderResponse}" />
This way it's enabled in all other phases like apply request values and update model values, allowing JSF to collect the submitted value and invoking the setter with it.
An alternative is to let the radio button use JSF ajax or <a4j:jsFunction> to update the dropdowns.

JSF component closing-off table cell

I'm trying to nest a table inside a h:panelGrid component, and h:selectOneMenu is screwing-up the formatting by closing off the cell it appears within and creating a new (and unwanted) row.
My code looks something like this:
<h:panelGrid columns="2">
[Other rows that work just fine]
<h:outputText value="Match [Stuff] to [More Stuff]:" />
<table>
<tr>
<th>[Stuff]</th>
<th>[More Stuff]</th>
</tr>
<tr>
<td>
<h:outputText value="Manually Created First Element of Stuff" />
</td>
<td>
<h:selectOneMenu value="#{bean.moreStuffSetting}">
<f:selectItem itemLabel="--None--" itemValue="" />
<f:selectItem itemLabel="Manual First Choice" itemValue="manual" />
<f:selectItems
value="#{bean.listOfMoreStuff}"
var="moreStuff"
itemLabel="#{moreStuff.name}"
itemValue="#{moreStuff.value}" />
</h:selectOneMenu>
</td>
</tr>
<ui:repeat value="#{bean.listOfStuff}" var="stuff">
<tr>
<td>
<h:outputText value="#{stuff.name}" />
</td>
<td>
<h:selectOneMenu value="#{bean.moreStuffSetting}">
<f:selectItem itemLabel="--None--" itemValue="" />
<f:selectItem itemLabel="Manual First Choice" itemValue="manual" />
<f:selectItems
value="#{bean.listOfMoreStuff}"
var="moreStuff"
itemLabel="#{moreStuff.name}"
itemValue="#{moreStuff.value}" />
</h:selectOneMenu>
</td>
</tr>
</ui:repeat>
</table>
</h:panelGrid>
The problem occurs with that first h:selectOneMenu element. (The h:selectOneMenu element inside ui:repeat is doing exactly what I expect it to, however.) I'm expecting "Manually Created First Element of Stuff" and that drop-down to appear as two cells in the same row. However, this is what's showing up in the generated HTML:
<tr>
<td>Manually Created First Element of Stuff</td>
<td>
</td>
<td></td>
</tr>
<tr>
<td><select...
Two rows. However, in the nested one below, I get this:
<tr>
<td>[Label I'm expecting]
</td>
<td><select...
... which is exactly how I expected it to behave.
What am I doing wrong? Am I misusing JSF somehow? Is there some face-palm-worthy typo in there I'm not seeing?
The <h:panelGrid> picks the first sibling in the JSF component tree to start a new table cell. The plain HTML <table> element which you've there isn't a JSF component.
Wrap it in a <h:panelGroup>.
<h:panelGrid columns="2">
<h:outputText value="Match [Stuff] to [More Stuff]:" />
<h:panelGroup>
<table>
...
</table>
</h:panelGroup>
</h:panelGrid>
An alternative is to just use <h:dataTable> instead.

How to rewrite JSF h:table into h:panelGrid

I need a way to create editable table like this. I interested is it possible to use h:panelGrid to display and edit the data. From my previews post I saw that it's possible to simple JSF table, but is this possible with h:panelGrid?
<table>
<ui:repeat var="elem" value="#{yourMB.yourDataList}">
<tr>
<td>#{elem.userid}</td>
<td>
<h:outputText value="#{elem.name}"
rendered="#{not elem.editable}" />
<h:inputText value="#{elem.name}" rendered="#{elem.editable}" />
</td>
<td>
<h:outputText value="#{elem.telephone}"
rendered="#{not elem.editable}" />
<h:inputText value="#{elem.telephone}"
rendered="#{elem.editable}" />
</td>
<td>
<h:commandLink value="Edit" rendered="#{not elem.editable}"
action="#{yourMB.editAction(elem)}" />
</td>
</tr>
</ui:repeat>
</table>
<h:commandButton value="Save Changes" action="#{yourMB.saveAction}" />
The answer is "NO". Try to use h:dataTable instead of h:panelGrid.

How to clear the password / login id fields on load

When i try to create a new user, the following fields (loginId which is an inputText) and (password which is an inputSecret) come with pre-loaded values. How do we clear these fields when the page is loaded
<s:decorate id="loginIdField" template="/layout/edit.xhtml">
<ui:define name="label">Desired Login Name</ui:define>
<a:region>
<h:inputText id="loginId" required="true" value="#{userHome.instance.loginId}"/>
<div class="actionButtons">
<a:commandButton id="submit" value="Check Availability"
action="#{userHome.isUniqueUsername(userHome.instance.loginId)}" reRender="loginIdField"/>
</div>
</a:region>
</s:decorate>
<table style="clear:both">
<tr>
<td>
<s:decorate id="passwordField" template="/layout/edit.xhtml">
<ui:define name="label">Password</ui:define>
<h:inputSecret id="password" required="true" redisplay="true" value="#{userHome.instance.passwordHash}"/>
</s:decorate>
</td>
<td>
<s:decorate id="passwordControlField" template="/layout/edit.xhtml">
<ui:define name="label">Retype Password</ui:define>
<h:inputSecret id="passwordControl" required="true" redisplay="true">
<s:validateEquality for="password" message="The passwords don't match, please enter again"/>
</h:inputSecret>
</s:decorate>
</td>
</tr>
</table>
This may have two reasons:
your instance is an already initialized object with set loginId and password
your browser recognizes the login fields and automatically fills-in the remembered values
They can be solved fairly easily:
during the initialization of the userHome bean create a new instance of User rather than load anything
Three options:
(preferred) set the following attribute: <h:inputText autocomplete="off" ..
change the id attribute of the fields to be different from those in the login form. for example id="registerLoginId".
alternatively you can use javascript -
window.onload() = function() {
document.getElementById("formId:fieldId").value = "";
}

JSF a4j:commandLink component doesn't work inside a4j:repeat

I have such code in my JSF template:
<h:form>
<table id="users" cellspacing="0">
<a4j:repeat var="person" value="#{personList}">
<tr>
<td class="col1">
<a4j:commandLink
disabled="#{!canCreatePerson}"
styleClass="#{canCreatePerson ? '' : 'inactive_link'}"
action="#{adminPageController.create}"
reRender="user-dialog-region"
timeout="5000"
limitToList="true"
ignoreDupResponses="true"
title="#{canCreatePerson ? messages['edit_user'] : ''}"
onclick="if (!ajaxSubmissionAllowed) {return false;}
ajaxSubmissionAllowed=false;"
oncomplete="ajaxSubmissionAllowed=true;">
<h:outputText id="userName" value="#{person.name}"/>
</a4j:commandLink>
</td>
</tr>
</table>
</h:form>
This perfectly works outside the a4j:repeat tag, but no action performs inside a4j:repeat like it's implemented in my template.
The problem was in SCOPE type of the variable personList, it was CONVERSATION, after I've changed it to PAGE everything works fine.
It's strange that I didn't see any error from SEAM.

Resources