Invoke aciton method with input value as parameter - ajax

I have this view:
<h:form id="carlin">
<h:outputText id="carlinInput" value="#{userBean.model.varAjax}"/>
<a class="btn" data-toggle="modal" href="#myModal" >Launch Modal</a>
</h:form>
And I have a modal dialog that shows another form:
<h:form>
<h:inputText value="#{userBean.model.varAjax}"/>
<h:commandLink action="#{userBean.processPage1()}" value="Ok">
<f:ajax render=":carlin:carlinInput" />
</h:commandLink>
</h:form>
I need to set the value typed on the <h:inputText> and pass it as a parameter to my <h:commandLink action="#{userBean.processPage1()}" value="OK">`
Here is my processPage1() method:
public void processPage1(String zip) {
this.model.varAjax = zip;
}
I have tried this:
<h:commandLink action="#{userBean.processPage1(userBean.model.varAjax)}" value="OK">
But it doesn't work. If I pass a hardcoded value, it works:
<h:commandLink action="#{userBean.processPage1('teste')}" value="OK">
But I need to pass what the user typed on that inputText to my action method. How can I achieve this?

This is not the right approach. You need to specify the client IDs of the input components which you need to process/execute by the execute attribute of <f:ajax>.
<h:form>
<h:inputText id="varAjax" value="#{userBean.model.varAjax}"/>
<h:commandLink action="#{userBean.processPage1}" value="Ok">
<f:ajax execute="varAjax" render=":carlin:carlinInput" />
</h:commandLink>
</h:form>
This way JSF will set the model value with the submitted value.
public void processPage1() {
System.out.println(model.getVarAjax()); // Look, JSF has already set it.
}
An alternative is to use execute="#form" which will process the entire form and this is what you usually need in standard ajaxified buttons.
<f:ajax execute="#form" render=":carlin:carlinInput" />
Note that componenent libraries like PrimeFaces and RichFaces have already made the #form the default execute attribute, so you don't need to explicitly specify it in their command components. In standard <f:ajax> it namely defaults to #this in command components which is indeed unintuitive.

Related

What is the difference b/w #form value and explicitly mentioning the component Ids in render attribute of <f:ajax>?

Consider the snippet:
<h:form>
<hr/>
<h:panelGrid columns="3">
Name:
<h:inputText id="nameId" value="#{ajaxBean.name}"
validator="nameValidator"
f5:placeholder="Enter your name ..."/>
<h:message id="msgNameId" showDetail="true"
showSummary="true" for="nameId"
style="color: red;"/>
Surname:
<h:inputText id="surnameId" value="#{ajaxBean.surname}"
validator="nameValidator"
f5:placeholder="Enter your surname ..."/>
<h:message id="msgSurnameId" showDetail="true"
showSummary="true" for="surnameId"
style="color: red;"/>
</h:panelGrid>
<h:commandButton value="Submit">
<f:ajax execute="#form"
render="#form" listener="#
{ajaxBean.upperCaseNameAndSurname()}"/
</h:commandButton>
<h:commandButton value="Cancel">
<f:ajax execute="#this"
render="#form"/>
</h:commandButton>
<h:commandButton value="Clear/Reset">
<f:ajax execute="#this"
render="#form"
listener="#{ajaxBean.cancelNameAndSurname()}"/>
</h:commandButton>
</h:form>
resetValues= "true" seems to work only if one mentions the component ids explicitly inside the render attribute of the <f:ajax> for the Submit button.
i.e render="nameId msgNameId surnameId msgSurnameId" rather than render="#form"
What exactly is the difference b/w these 2 forms?
The invalid values are still there after re-render if the value is (#form) for render attribute for Submit button.
I definitely remembered one of the comments by BalusC,
When validations phase has failed due to a conversion or validation
error anywhere, components which successfully passed validation will
return local value and components which failed validation will return
submitted value.
If the name is valid and the surname is not (or any other combination involving invalid values), then after submit and clear/ reset, the input field*(i.e the valid field)* for the name is not cleared. Even though the whole form was re-rendered, I see only the field for which validation failed was cleared. Why?
Does the above comment signifies some relation with the above problem?
The cancelNameAndSurname method just do this thing-
name = ""
surname = ""
I know for sure that one of the solutions to resolve this is -
<f:actionListener type="org.omnifaces.eventlistener.ResetInputAjaxActionListener"/>

How to use ajax update content but without submit button

I have a jsf code like this. When user finish to input name and comment and press 'Enter', the content can show in 'Content........' this part.
<h:form id="all_comments">
Content........
</h:form>
<h:form id="submit_comment">
<h:inputText id="name_box" value="#{ManagedBean.user}"/>
<h:inputText id="content_box" value="#{ManagedBean.comment}" />
</h:form>
I want to use ajax finish it, and I try like this:
<h:form id="all_comments">
Content........
</h:form>
<h:form id="submit_comment">
<h:inputText id="name_box" value="#{ManagedBean.user}"/>
<h:inputText id="content_box" value="#{ManagedBean.content}">
<f:ajax event="keydown"
listener="#{ManagedBean.addComment}"
execute="comment_name_box comment_content_box"
rendered=":all_comments" />
</h:inputText>
</h:form>
But I failed, can I achieve that when user press 'Enter', data will be processed by ManagedBean, then using ajax update the page.
You've got some points missing:
You need to send an AJAX call only when enter key was pressed, so you need to bind <h:inputText> tag's onkeydown attribute with JavaScript code for that;
<f:ajax> attribute is render, not rendered;
submit_comment form should be rerendered as well, so that new data will be presented to the user, and the placeholders have to be refreshed in AJAX listener as well.
Here is the solution when you want to submit the second form on that event:
<h:form id="all_comments">
Content........
</h:form>
<h:form id="submit_comment">
<h:inputText id="name_box" value="#{managedBean.user}"/>
<h:inputText id="content_box" value="#{managedBean.content}"
onkeydown="return (event.keyCode == 13);">
<f:ajax event="keydown"
listener="#{managedBean.addComment}"
execute="#form"
render="#form :all_comments" />
</h:inputText>
</h:form>
with
public void addComment(AjaxBehaviorEvent abe) {
comments.add(new Comment(user, content));
user = "";
content = "";
}

JSF Ajax reset previously rendered input component values?

I have a small (but vital) problem with JSF and ajax. The form is here:
<h:form>
<h:panelGrid id="pg1" columns="2">
<h:outputText value="Type: "/>
<h:selectOneMenu id="selectOne" value="#{personBean.type}">
<f:selectItems value="#{listBean.personTypes}"/>
<f:ajax event="valueChange" render="pg2"/>
</h:selectOneMenu>
</h:panelGrid>
<h:panelGrid id="pg2" columns="2">
<h:outputText value="Really bad?" rendered="#{personBean.type=='BAD'}"/>
<h:selectBooleanCheckbox id="checkbox" value="#{personBean.reallyBad}" rendered="#{personBean.type=='BAD'}">
<f:ajax event="click"/>
</h:selectBooleanCheckbox>
</h:panelGrid>
<h:commandButton value="Ajax Submit" action="#{personBean.printValues}">
<f:ajax execute="#form"/>
</h:commandButton>
</h:form>
The PersonBean is a simple bean with an enum PersonType that has two values: NICE, BAD and a Boolean called reallyBad. The ListBean returns the enum values in a list to populate the selectOneMenu.
Basically when I select BAD the panel for the boolean checkbox is rendered where I can tick it to say a person is reallyBad. I can then submit the form if I wish. The problem is when I tick the checkbox and then select NICE again, the checkbox is still ticked even though it is not rendered. So when I submit my form the person can be NICE and reallyBad, which doesn't make sense.
Rather than having to select BAD again to uncheck the box, is their a way that I can reset the checkbox and its input value to false when NICE is selected? I'm a bit of a noob to ajax with JSF! Thanks.
ps. I am printing the values of the two inputs on submit with the commandButtons action to verify the results...
You need to manually clear the checkbox when you change the menu.
<f:ajax listener="#{personBean.setReallyBad(false)}" render="pg2" />
By the way, the both <f:ajax event> values as you've in your code are the default values already. Just omit them.

Rendering other form by ajax causes its view state to be lost, how do I add this back?

I have
<h:form>
<h:commandLink action="#{my_fake_ajax_link}">
<h:outputText value="Link" />
<f:ajax render=":mydiv" />
</h:commandLink>
</h:form>
<h:panelGroup layout="block" id="mydiv">
<h:form>
<h:commandLink action="#{mybean.delete(0)}">
<h:outputText value="Here" />
<f:ajax render="#form" />
</h:commandLink>
</h:form>
</h:panelGroup>
When I click once on "my_fake_ajax_link", then I have to click twice on "delete" link. This is only an example. I don't have this real case. I have multiple forms on a page and I can't just add all of them in a single form.
I checked what the problem is and it is:
When you click on "my_fake_ajax_link", the mydiv refreshs with ajax as it should.
ViewState of the refreshed form on ajax is missing.
How can I add the ViewState? How can I make it work without using only one form? This looks like an JSF bug to me. I don't want to refresh that div automatically with
jQuery("#mydiv").load(document.location.href);
but I will in my worst case possible.
This is a known problem in the auto-included jsf.js library of JSF which handles ajax responses. See also JSF spec issue 790 which is fixed in the upcoming JSF 2.3. In the meanwhile, with JSF 2.0/2.1/2.2, you have to explicitly specify the ID of the other <h:form> inside the render attribtue to trigger proper addition of the view state.
<h:form>
<h:commandLink action="#{my_fake_ajax_link}">
<h:outputText value="Link" />
<f:ajax render=":mydiv :mydivForm" />
</h:commandLink>
</h:form>
<h:panelGroup layout="block" id="mydiv">
<h:form id="mydivForm">
<h:commandLink action="#{mybean.delete(0)}">
<h:outputText value="Here" />
<f:ajax render="#form" />
</h:commandLink>
</h:form>
</h:panelGroup>
No, this does not cause any overhead or markup duplication in the ajax response. Alternatively, use OmniFaces fixviewstate.js.
See also:
Communication in JSF 2.0 - Ajax rendering of content which contains another form
h:commandButton/h:commandLink does not work on first click, works only on second click
Workaround for that:
First you need to set an onevent handler for the button that sends the ajax request:
<h:form id="newComment">
<h:commandButton id="saveNewComment" action="#{postBean.actionSaveNewCommentAjax}" value="#{rb['speichern']}">
<f:ajax execute="#form" render=":commentsBox" onevent="function(data) { fixOtherFormsViewState(data, 'newComment') }" />
</h:commandButton>
</h:form>
Then you need to declare this javascript methods that will take the correct viewState value and add it to all forms which doesn't have it:
<h:outputScript>
function fixOtherFormsViewState(data, goodFormId) {
if (data.status != "success") {
return;
}
var viewState = jQuery("#" + goodFormId + " input[name='javax.faces.ViewState']").val();
jQuery("form:not(:contains(input[name='javax.faces.ViewState']))").each(function (idx, elem) {
var form = jQuery(elem);
var input = jQuery("<input type='hidden' name='javax.faces.ViewState' />").val(viewState);
form.append(input);
});
}
</h:outputScript>

How to pass an iterated parameter via ajax to a backing bean method

So, I have a dataTable that looks like this:
<h:form>
<h:dataTable value="#{backingBean.employeeLineItems}" var="emp">
<h:column>
<f:facet name="header">First</f:facet>
#{emp.lastname}
</h:column>
<h:column>
<f:facet name="header">Last</f:facet>
#{emp.firstname}
</h:column>
<h:column>
<f:facet name="header">Actions</f:facet>
<h:commandButton value="View Details">
<f:ajax execute="#{setCurrentEmployeeId(emp.id)}" render="employeeDetails"/>
</h:commandButton>
</h:column>
</h:dataTable>
<h:outputText value="#{backingBean.employeeDetails}" id="employeeDetails"/>
</h:form>
For each row of the datatable, there is a button that I want to, when clicked, ajax the employeeLineItem id value over to a method that sets that id in the backing bean, and then renders the outputText tag with id "employeeDetails" (The getEmployeeDetails method would use the employeeLineItem id to get the right employee details object from the database, of course)
My solution doesn't seem to be working, does anyone know what I'm doing wrong?
<h:commandButton value="View Details">
<f:ajax execute="#{setCurrentEmployeeId(emp.id)}" render="employeeDetails"/>
</h:commandButton>
This is wrong. The execute attribute of <f:ajax> should point to a space separated collection of component client IDs which are to be submitted and processed in the server side (the same way as you specify the render attribute with a space separated collection of component client IDs which are to be updated/re-rendered after the ajax request). In your particular case, it should have been the ID of the datatable or the form, or just #form to generically refer the parent form.
The action method wherein you pass the row ID should be definied in the action attribute of the <h:commandButton> instead. So, this should do:
<h:commandButton value="View Details" action="#{backingBean.setCurrentEmployeeId(emp.id)}">
<f:ajax execute="#form" render="employeeDetails"/>
</h:commandButton>
(note that I fixed the missing managed bean name in the action method)
By the way, are you aware that you can also just pass whole objects along as arguments in EL?
<h:commandButton value="View Details" action="#{backingBean.setCurrentEmployee(emp)}">
<f:ajax execute="#form" render="employeeDetails"/>
</h:commandButton>
This way you don't need to reload the employee from the DB.

Resources