Execute other form field value in JSF ajax - forms

Consider the following JSF 2.x markup:
<h:form id="form1">
<h:inputText id="input" value="#{testBacking.input}"/>
</h:form>
<h:form id="form2">
<h:commandButton value="go" action="#{testBacking.go()}">
<f:ajax execute="#all" render="output"/>
</h:commandButton>
<h:outputText id="output" value="#{testBacking.input}"/>
</h:form>
The action method as follows:
public void go() {
System.out.println("go() is called");
System.out.println("input: "+ input);
}
The input value does not submitted to the server upon clicking the button.
Are there any ways to submit the input value to the server (while keeping the input in a different form)?
If you can only submit fields from the same form, then what is the different between the following two?
<f:ajax execute="#all" render="output"/>
<f:ajax execute="#form" render="output"/>

A quick search of jsf execute=#all vs execute=#form yields some results:
JSF: Execute values of multiple forms
What is <f:ajax execute="#all"> really supposed to do? It POSTs only the enclosing form
In essence, the JSF processing works ok but HTML only sends the form that contains the ajax (I suspect HTML specifies a separate request for each form).

Related

Create a popup inside a form

I want to include a popup inside a form. The normal way to do that is to have 2 forms like:
<div class="wrapper" >
<h:form>
<h:panelGroup id="id1" layout="block">
<ui:include src= content1 />
</h:panelGroup>
</h:form>
</div>
<h:form id="modalId">
<ui:include src= popupContent >
</ui:include>
</h:form>
and render with a button inside content1, the form "modalId" that contains the popUp.
I have the popup form in an external component that is included inside "content1". Due to the popup form is inside the other form,it isnt well rendered. How can I fix that? The idea is to use that component that is common for all my xhtml views
The way i was writing my own components was to rely on the existance of the external form. That is, i did not include any form elements inside the component.
If there was a need to reference the outer form element then i would just pass the from id as one of the attributes of the interface. Composite components are really useful for this kind of stuff:
<composite:interface>
<composite:attribute name="formId" type="java.lang.String" />
</composite:interface>
<composite:implementation>
<h:commandButton value="button" action="someaction">
<f:ajax execute="#{cc.attrs.formId}" render="#{cc.attrs.formId}" />
</h:commandButton>
</composite:implementation>
Then you include that in your outer form (assuming 'comp' is your namespace for composite components and 'modal' is the name of the file containing the component):
<h:form id="myForm">
<comp:modal formId="myForm"/>
</h:form>
Go through this tutorial if you are not familiar with them:
http://docs.oracle.com/javaee/6/tutorial/doc/giqzr.html

How to use EL with <ui:repeat var> in id attribute of a JSF component

I have following code:
<ui:repeat var="class2" value="#{bean.list}" varStatus="status">
<h:form id="#{class2.name}">
<h:outputText value="#{class2.name}" />
</h:form>
</ui:repeat>
However, when I open the page, it errors as follows:
component identifier must not be a zero-length String
But it is properly printed in the <h:outputText>. How is this caused and how can I solve it?
You can use EL in the id attribute of a JSF component, but the EL variable has to be available during view build time, while the JSF component tree is to be built. However, the <ui:repeat> runs during view render time, while the HTML output is to be generated based on JSF component tree. The <ui:repeat var> is not available during view build time and #{class2.name} evaluates to null which totally explains the error you got. That it works in <h:outputText> is because it runs during view render time.
If you replace <ui:repeat> by <c:forEach>, which runs during view build time, then it'll work as you intented. The <c:forEach> will namely generate physically multiple <h:form> components in the JSF component tree which each generate individually their own HTML output (in contrary to <ui:repeat>, wherein the very same <h:form> component is been reused multiple times to generate HTML output).
<c:forEach var="class2" items="#{bean.list}" varStatus="status">
<h:form id="#{class2.name}">
<h:outputText value="#{class2.name}" />
</h:form>
</c:forEach>
However, I really wonder why you need to do that. There's usually no need to dynamically assign component IDs. JSF will already ensure the uniqueness of the ID. The below example,
<ui:repeat var="class2" value="#{bean.list}" varStatus="status">
<h:form id="form">
<h:outputText value="#{class2.name}" />
</h:form>
</ui:repeat>
will end up in multiple forms with each an unique ID, suffixed with iteration index of the <ui:repeat>. If you actually need to use #{class2.name} for some JavaScript/jQuery purposes (you did nowhere state the concrete functional requirement in the question for which you thought that this would be the right solution, so it's merely guessing), then just wrap it in a plain vanilla HTML element:
<ui:repeat var="class2" value="#{bean.list}" varStatus="status">
<div id="#{class2.name}">
<h:form id="form">
<h:outputText value="#{class2.name}" />
</h:form>
</div>
</ui:repeat>
Or set it as style class of a JSF component, which is also just selectable via a CSS selector:
<ui:repeat var="class2" value="#{bean.list}" varStatus="status">
<h:form id="form" styleClass="#{class2.name}">
<h:outputText value="#{class2.name}" />
</h:form>
</ui:repeat>
See also:
JSTL in JSF2 Facelets... makes sense?

How to dynamically add new row to p:dataTable without validating the form?

I'm developing a form for adding/editing product prices with JSF and PrimeFaces. A single product can have multiple prices depending on volume which is shown in a <p:dataTable>.
The backing bean:
#ManagedBean
#ViewScoped
public class ProductBean {
protected Product product;
protected List<ProductPrice> productPrices;
public void addNewPrice() {
ProductPrice productPrice = new ProductPrice();
productPrice.setPrice(new BigDecimal(0));
this.productPrices.add(productPrice);
}
// ...
}
The Facelet page:
<h:form id="productForm">
<p:inputText value="#{productBean.product.name}" required="true">
<f:ajax event="blur" render="nameMessage" />
</p:inputText>
<p:message id="nameMessage" for="name" />
<p:dataTable id="pricesList" ...>
</p:dataTable>
<p:commandButton value="Add another price" update="pricesList" action="#{productBean.addNewPrice()}" />
<p:commandButton value="Submit" action="#{productBean.submit}" />
</h:form>
The first button "Add another price" does, what it is supposed to do: Adding a new row to "pricesList". But only if form is valid (form is invalid, if product-name is not set).
My problem is, that I am having two commandButtons for the form, but I don't know how to get my wished functionallity without a commandButton. I tried a lot of ways: Changing the "Add another price" to a standard <p:button> with ajax-functionality; doesn't work because of buttons' outcome. I tried "type=button" for this button, but in this case simply nothing happens.
Are there any suggestions have to achieve my wished functionality? It is not necessary to have a button solving my problem.
The <p:commandButton> submits and processes by default the entire form. This will indeed validate all input fields. You can control this with the process attribute which thus defaults to #form. In your particular case, you could just use #this so that only the command button's own action is invoked.
<p:commandButton value="Add another price" process="#this" update="pricesList" action="#{productBean.addNewPrice()}" />
what's wrong with using p:commandButton to add rows dynamically?
If i undersatnd your question right, you obviously need a request to your managed bean in order to add your new row information into your datatable list. you could always go for p:commandLink if you are not comfortable with p:commandButton. and for editing the row data you could use p:rowEditor with p:datatable.
check out the showcase example for datatable row editing
hope this helps :)

CommandButton's action URL depending on the form content

I'm doing a simple search engine for my web app and I'm facing a problem.
My search.xhtml works by getting a parameter, so that search.xhtml?key=lol will return the results for "lol".
What I need to do is that my search commandButton will redirect do search.xhtml?key=INPUT TEXT CONTENT.
Here's my simple code :
<div id="searchBox">
<pou:panel id="searchPanel">
<h:form>
<h:inputText id="searchInput" value="#{dispensaRicercaBean.query}" size="99" maxlength="99"/> <pou:commandButton icon="ui-icon-search" action="ricerca?faces-redirect=true"/>
<pou:watermark value="Search" for="searchInput"/>
</h:form>
</pou:panel>
</div>
where dispensaRicercaBean is #RequestScoped and my result page loads the data calling executeQuery(#{request.getParameter('key')) (a rough example, actually there are some differences)
How can I do that?
Use a plain HTML <form>
<form action="ricera.xhtml">
<h:inputText id="key" size="99" maxlength="99" />
<pou:watermark value="Search" for="key" />
<pou:button icon="ui-icon-search" onclick="submit(); return;" />
</form>

Submit a JSF form using GET

How do I submit a form to the same page and use GET parameters?
JSF page contents:
<f:metadata>
<f:viewParam name="item1" value="#{bean.item1}"/>
<f:viewParam name="item2" value="#{bean.item2}"/>
</f:metadata>
...
<h:form>
<h:inputText value="#{bean.item1}"/>
<h:inputText value="#{bean.item2}"/>
<h:button value="Submit" >
<f:param name="item1" value="#{bean.item1}"/>
<f:param name="item2" value="#{bean.item2}"/>
</h:button>
</h:form>
If I request the page: form.jsf?item1=foo&item2=bar, it will populate the text fields, but the form submission to itself doesn't seem to work.
Replace <h:button> by
<h:commandButton value="Submit" action="form?faces-redirect=true&includeViewParams=true"/>
It effectively fires a PRG (Post-Redirect-Get) which will include the <f:viewParam> params in the query string. Noted should be that the target page must have exactly same <f:viewParam>.
Another solution is to use a plain HTML <form> instead of <h:form>, give the input elements an id matching the parameter name and use a plain <input type="submit">. You can of course also use plain HTML <input type="text"> here.
<form>
<h:inputText id="item1" value="#{bean.item1}"/>
<h:inputText id="item2" value="#{bean.item2}"/>
<input type="submit" value="Submit" />
</form>
You should still keep the <f:viewParam> in both sides. You only need to realize that conversion/validation couldn't be done in this form, they have to be performed via the <f:viewParam> on the target page.
See also:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
You could also register a NavigationHandler that handles a keyword like 'self' and redirects to the the current view and adds the necessary query parameters.