Can we create textbox right next to selectonemenu component when we fire selectoneMenu valueChangeListener event - jsf

want to create textbox on the fly is it possible?
Select Report to run:
<h:selectOneMenu value="#{reportBean.selectReport}">
<f:selectItems value = "#{reportBean.allReports}" />
<f:ajax listener="#{reportBean.getReqID}" render="reqID"> </f:ajax>
</h:selectOneMenu>

Seems like you want to show/hide the <h:inputText> based on the selected value on your <h:selectOneMenu>. Yes, this can be easily achieved with plain JSF.
Note that if you use set the rendered attribute as false the component won't appear in the component tree, so there will be no way it can't be referenced for any call (not even ajax calls). In order to update it, you should wrap the component inside another component like <h:panelGroup> and render the wrapper. Basic example:
<h:form id="frmRep">
<h:selectOneMenu value="#{reportBean.selectReport}">
<f:selectItems value = "#{reportBean.allReports}" />
<!--
assuming your reportBean.getReqID method will change the value of
reportBean.showReqID attribute to render/not render it and works well
-->
<f:ajax listener="#{reportBean.getReqID}" render="pnlRepName" />
</h:selectOneMenu>
<h:panelGroup id="pnlRepName">
<h:inputText id="reqID" rendered="#{reportBean.showReqID}"
value="#{reportBean.reportName}" />
<h:panelGroup>
</h:form>
For this specific requirement instead, I won't recommend using an ajax call since it has to go to the server to only check if the component should or should not be showed to the user. I would opt for a JavaScript solution to handle this just on client side.

Related

Javascript error in XHTML page in JSF 2

I have the following code in an xhtml page in JSF 2. But when the page loads I get an javascript error that
document.getElementById("country") is null or not an object.
Why is this happening?
<h:form>
<h:panelGrid columns="2">
Selected country locale :
<h:inputText id="country" value="#{country.localeCode}" size="20" />
Select a country {method binding}:
<h:selectOneMenu value="#{country.localeCode}" onchange="submit()"
valueChangeListener="#{country.countryLocaleCodeChanged}">
<f:selectItems value="#{country.countryInMap}" />
</h:selectOneMenu>
<script>
alert("hi");
document.getElementById("country").disabled=true;
</script>
</h:panelGrid>
</h:form>
It's not finding your component. Since your <h:inputText> is inside of an <h:form> the id will have the following pattern
formName:componentName. Since you did not specify an id for <h:form>, JSF will generate one for you. That's why you are seeing j_id1926454887_72d35e53:country where j_id1926454887_72d35e53 is the form id. If you want to deal with simpler id, then you should add an id value to your <h:form>. For example
<h:form id="form">
<h:inputText id="country" value="#{country.localeCode}" size="20" />
</h:form>
The id for <h:inputText> will now be form:country.
Even simpler, you could simply add prependId = "false" to your form
<h:form prependId="false">
and now your id for <h:inputText> will simply be country.
How can I get this id dynamically?
I'm going to modify your code slightly to achieve what you want (I'm thinking that you want to disable the input based on a specific event). Consider this simpler example
<h:form>
<h:inputText id="country" value="#{country.localeCode}" size="20" onclick="disableInputText(this.form)" />
</h:form>
Here I'm attaching a javascript function to an HTML DOM Event handler. In this case, I want the input to be disabled when I click on it (hence onclick). I'm also passing the form as a reference in the function. Then, define your Javascript like this.
<script>
function disableInputText(form) {
form[form.id + ":country"].disabled = true;
}
</script>
We simply grab the input in the javascript with the corresponding id via the object form and set its disabled attribute to true. (You can sort of view the form object as Map).
Also check the link below for more attributes of <h:inputText> and the different handlers you can use (the ones with on as prefix).
inputText Tag Attribute.
Also, check out the answer with the most votes to get a bigger picture on how ids are generated and other ways on how they can be determined.
How can I know the id of a JSF component so I can use in Javascript
It's seems to be a naming issue. the id of the field is not rendered as country.
i found a question that seems relevant. Composite components & ID

JSF onclick event on combobox

I don't know how to implement onclick event on a combobox, my boss want me to do is once the user click a value in the combobox it automatically search and display all the value of the selected/click item. First question is it possible to have an onclick event on a JSF page without using any javascript/jquery? Right now I'm using ADF for designing the interface. Second question how can I implements this onclick event on my combobox?
There are a couple of ways to achieve this:
Use a valueChangeListener and execute your query when it fires.
Set autoSubmit="true" and when the bound value changes, execute your query.
Only selecting a value in a dropdown won't submit your form. This is not about JSF but HTML .. so without any JS i think it's not possible.
I do not know anything about ADF in special but in plain JSF you just have to add an ajax-event to your dropdown (e.g. in primefaces)
<h:form id="id1">
<p:selectOneMenu id="id2" value="#{myBean.value}"
immediate="true" editable="true" >
<f:ajax execute="#this" listener="#{myBean.doSomeAction}" />
<f:converter converterId="myConverter" />
<f:selectItems value="#{myBean.availableOptions}" />
</p:selectOneMenu>
</h:form>

Show Richfaces Component on event selection

I would like to know how could I retrieve my jsf component value, when an event is executed. For example consider this component:
<rich:select id="selectEmpresa"
value="#{macroprocesoController.empresaSeleccionada}"
converter="genericConverter" enableManualInput="true" onchange="if(!#{rich:component('selectEmpresa')}.getValue()) return false;">
<f:selectItems value="#{selectItemsController.empresaItems}" />
<a4j:ajax execute="#this" render="macroProcesosTable" event="selectitem" listener="#{macroprocesoController.empresaSelectedListener}"></a4j:ajax>
<a4j:ajax execute="#this" render="macroProcesosTable" event="change" listener="#{macroprocesoController.empresaSelectedListener}"></a4j:ajax>
</rich:select>
What I want is to conditionally execute the a4j:ajax for the change event, so that when the component executes the selectitem event, and thus setting a value, the change event will be bypassed. However this is not working, any suggestions or a way to do what I need?
onchange="if(!#{rich:component('selectEmpresa')}.getValue()) return false;"
This expression is evaluated when the view is rendered, not when the DOM event executes (check the generated HTML source to see it yourself). You'd need to use JavaScript instead to get the current value. The following should do:
onchange="if (!this.value) return false;"
or just
onchange="return !!value;"

Sending JSF parameters within Richfaces a4j:repeat

I'm attempting to put a few drop down menus inside of an a4j:repeat. The values for the second drop down are dependent on the value selected in the first. Below is the code I am attempting to use, but it passes a blank parameter:
<a4j:repeat id="localRepeat" var="local" value="#{InstanceController.instance.locations}" rowKeyVar="row">
<h:panelGrid columns="2">
<h:outputLabel value="Theater:" />
<h:selectOneMenu id="theater" converter="#{TheaterConverter}" value="#{local.theater}">
<f:selectItems id="theaters" value="#{InstanceController.allTheaters}" />
<a4j:support event="onchange" action="#{InstanceController.getAllCountriesInTheater}" reRender="country" >
<f:param name="theater" value="#{local.theater.id}"/>
</a4j:support>
</h:selectOneMenu>
<h:outputLabel value="Country:" />
<h:selectOneMenu immediate="true" id="country" converter="#{CountryConverter}" value="#{local.country}">
<f:selectItems value="#{InstanceController.allCountriesInTheater}" />
<a4j:support event="onchange" reRender="state" />
</h:selectOneMenu>
</h:panelGrid>
<rich:spacer height="10px" />
</a4j:repeat>
If I change the f:param to send "1" instead of "#{local.theater.id}" it works as expected.
Is there a way to get the selected value of the first drop down and send it as a parameter?
This reason this doesn't work is that when the f:param tag is rendered, the current value of local.theater.id is already assigned to the parameter. So the theater param will contain the id of the theater that was selected when the page was rendered - probably null because no theater has been selected yet.
What you are trying to do is far more easy:
Just remove the f:param and use the property directly. When the a4j:support tag triggers because the selectbox value was changed, jsf will validate your form tags and assign the appropriate model values. So, when the getAllCountriesInTheater action gets executed, the local.theater property will already contain the selected theater.
Depending on how your backing beans are designed, you will probably need a parameter to identify the location for which the selectbox was changed, so the getAllCountriesInTheater action will know in which of the locations to look for the selected theater.

JSF ReRender support with selectBooleanCheckbox

I have a JSF page on which I want to have a checkbox that, when clicked, will add/remove certain other form fields from the page. Here is the (simplified) code I currently have for the checkbox:
<h:selectBooleanCheckbox title="showComponentToReRender" value="#{backingBean.showComponentToReRender}">
<a4j:support event="onsubmit" reRender="componentToReRender" />
</h:selectBooleanCheckbox>
Here is the code for the component I want to hide:
<h:selectOneMenu id="componentToReRender" value="#{backingBean.value}" rendered="#{valuesList.rowCount>1 && backingBean.showComponentToReRender}">
<s:selectItems value="#{valuesList}" var="value"/>
</h:selectOneMenu>
Currently, clicking the checkbox does nothing; that "selectOneMenu" will not go away. What am I doing wrong?
You need to wrap the componentToReRender in either:
<h:panelGroup id="componentToReRenderWrapper">
or
<a4j:outputPanel id="componentToReRenderWrapper">
So, effectively you will have:
<h:panelGroup id="componentToReRenderWrapper">
<h:selectOneMenu id="componentToReRender" value="#{backingBean.value}" rendered="#{valuesList.rowCount>1 && backingBean.showComponentToReRender}">
<s:selectItems value="#{valuesList}" var="value"/>
</h:selectOneMenu>
</h:panelGroup>
and change the reRender="componentToReRenderWrapper" in case you use panelGroup, or remove that attribute, in case you use outputPanel.
Found the exact explanation in the RichFaces docs:
Most common problem with using reRender is pointing it to the component that has a "rendered" attribute. Note, that JSF does not mark the place in the browser DOM where the outcome of the component should be placed in case the "rendered" condition returns false. Therefore, after the component becomes rendered during the Ajax request, RichFaces delivers the rendered code to the client, but does not update a page, because the place for update is unknown. You need to point to one of the parent components that has no "rendered" attribute. As an alternative, you can wrap the component with layout="none" .
Don't forget to set ajaxRendered="true" on the a4j:outputPanel

Resources