Add action to AjaxBehaviorEvent event - ajax

Currently I am working on a spring migration project. Since a4j:support is no longer supported I had to change those tags to a4j:ajax tags, but a4j:ajax tags do not have the action attribute. The systems is currently very heavily based on a seam pageflow which depend heavily on actions for it's navigation rules.
I was wondering if anyone knew an easy way in which I could just add an action to a AjaxBehaviorEvent so that I could pass in a value for the pageflow navigation? I have attempted to call the seam navigation handler directly and I keep getting a pageflow not initiated exception.
Here is an example of one of our pageflow pages if that helps
<page view-id="/customerProfileSetup.xhtml"
name="readProfile">
<redirect/>
<transition name="readProductProfileSetup"
to="productProfileSetup">
<action
expression="#{profileSetup.load}" />
</transition>
</page>
Ajax tag:
<a4j:ajax event="change" render="#all" listener="#{pageflowUtil.processPageflowAjaxBehavior}"/>
Method:
public void processPageflowAjaxBehavior(AjaxBehaviorEvent event) {}

Related

Best way to validate ajax updates in JSF 2.0?

Our team is writing its first JSF 2.0 application since using Stripes for many years, and I have some questions on the best way to use the f:ajax tag and validate the input.
A lot of questions I've seen answered have a form with multiple inputs and then a submit button), but we would like to maintain individual input fields updated immediately upon change and persisted to the database (with no submit button. We had this working fine in Stripes using Prototype's Ajax.Request, but it was an extra step I'd like to avoid if possible.
Essentially we have a page with a bunch of inputs on it directly backed by beans, for example:
<h:inputText id="name" value="#{personController.name}" >
<f:ajax listener="#{personController.ajax}" />
</h:inputText>
As you may know, by the time the listener is invoked, the value of name has already been changed on the bean. This would be convenient, but I have a few problems with it:
the listener doesn't obviously know which value of the bean was changed
the value has already been changed, I can't perform any server side validation on it
I don't know what the old value of name is even if I could perform some sort of validation on it, I wouldn't know what to set the value back to
Right now it's looking like we'll have to implement some kind of javascript middleman to take in what property changed and the new value, send that to the Controller, and have it perform validation, updating the database, sending back something to render, etc. But like I said, this is what we used to do with Stripes and I'd really like to use something more native.
I did see that if we wanted some kind of Submit button on the page we could use something like the valueChangeListener attribute, but I'd also like to avoid massive submits.
I included the OpenFaces tag because we're already using that for datatables, so if there's something nice in there we're open to using it. But as far as I can tell their o:ajax tag isn't that much more powerful than JSF's f:ajax.
Thanks!
You're looking in the wrong direction to achieve the concrete functional requirement of validating an input field. You should use a normal JSF validator for this, not some ajax listener method which runs at the wrong moment (the INVOKE_ACTION phase instead of PROCESS_VALIDATIONS phase) and where you don't directly have a hand at the model value. The ajax listener method is merely to be used to execute some business logic based on the current model value(s).
JSF has several builtin validators behind the required attribute and several <f:validateXxx> tags. You can even create custom validators by implementing the Validator interface.
E.g. checking the requireness:
<h:inputText ... required="true">
<f:ajax />
</h:inputText>
Or checking if it matches a pattern using one of the various <f:validateXxx> tags:
<h:inputText ...>
<f:validateRegex pattern="[a-z]+" />
<f:ajax />
</h:inputText>
Or using a custom validator:
<h:inputText ...>
<f:validator validatorId="myValidator" />
<f:ajax />
</h:inputText>
with
#FacesValidator("myValidator")
public class MyValidator implements Validator {
#Override
public void validate(FacesContext context, UIComponent component, Object value) {
if (value is not valid) {
throw new ValidatorException(new FacesMessage(...));
}
}
}
The <f:ajax> is merely there to submit the current input field during the HTML DOM change event (or click event in case of checkboxes/radiobuttons). You don't necessarily need a <f:ajax listener> method in order to submit the current input field by ajax. If you want to hook on a value change event, just use valueChangeListener.
<h:inputText ... valueChangeListener="#{bean.valueChanged}">
<f:ajax />
</h:inputText>
with
public void valueChanged(ValueChangeEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getValue();
UIComponent component = event.getComponent();
// ...
}
Note that this will only be invoked when validation has passed on the particular component.

JSF2 HTML5 input (email) does not update models

I've got a problem considering updating my backing-bean within an ajax-roundtrip in a JSF2 application if the value is bound to a html5 input type=email.
First of all, I created an "Html5InputRenderer", so that the JSF-runtime can create the html5-markup for a , in order to write
The central "magic" the "Html5InputRenderer does is:
markup.replaceAll("type=\"text\"", "type=\"email\"");
within the overridden method encodeEnd(..) of javax.faces.renderer.Renderer.
This h:input is put in to a form and enriched with f:ajax:
<h:form id="form">
<f:ajax render="testOut">
<h:inputText id="test" renderedType="email" value="#{testBean.value}" />
</f:ajax>
<h:outputText id="testOut" value="#{testBean.value}" />
</h:form>
The atribute 'renderedType' is the hint for the JSF-"Html5InputRenderer" to render the html5 markup for the h:input
Test the snippet. It will not update #{testBean.value} although an ajax roundtrip is invoked by the JSF-runtime.
Test the snippet removing the attribute 'renderedType', everything works like expected.

Action not triggered when button is enabled/disabled with ajax

I am stuck with a problem that doesnt make any sense to me. I have a listbox which fires selectionChange-Events with simple Ajax. The idea is that the edit-button isnt enabled until a item in the list is selected. So I created the following code.
<h:form>
<h:selectManyListbox value="#{bean.selectedIds}">
<f:selectItems value="#{bean.listOfItems}" />
<f:ajax render="edit"
listener="#{bean.selectionChanged}" />
</h:selectManyListbox>
<br />
<h:commandButton id="add" value="#{msgs.add}"
action="#{bean.addNew}" />
<h:commandButton id="edit" value="#{msgs.edit}"
disabled="#{bean.editButtonDisabled}"
action="#{bean.edit}" />
</h:form>
The button is enabled and disabled as I wish but as it turns out, the edit-button isnt triggering any action (I added some sysout to the add- and edit-method in the bean and the edit-method is never called)...instead the html changes. The above code is nested in a simple div. When I click edit, the whole form is outside of that div.
When I add this ajax-behavior to the add-button, the same happens there and vice versa, when I remove the disabled-attribute from the edit-button everything works???
I already had a look at BalusC answer here but I couldnt find any mistake related to that list. No nested forms and so on...its just a simple page with a template.
I am using Mojarra 2.1.2 on JBoss 7.1.Final.
Any help is appreciated. Thanks
This issue is covered by point 5 of the answer which you've linked.
The rendered attribute of the component and all of the parent components should not evaluate to false during the apply request values phase of the form submit request. JSF will namely recheck it then as part of safeguard against tampered/hacked requests. Putting the bean in the view scope and/or making sure that you're preinitializing the condition in (post)constructor of the bean should fix it. The same applies to the disabled attribute of the component, which should not evaluate to true during processing the form submit.
I suggest to change #RequestScoped on BikeManagementPanelBean to #ViewScoped.
try something like this
<h:commandButton id="edit" value="#{msgs.edit}"
disabled="#{bikeManagementPanelBean.editButtonDisabled eq false}"
action="#{bean.edit}" />
try to wrap it again with the <h:panelGroup> and render the instead of the button...

JSF2 preRenderComponent is called always when f:ajax is executed

I have an JSF page backed by NewsBean.java which has <f:event type="preRenderComponent" listener="#{newsBean.init}" /> as bean initializer.
There is a button at the bottom of the page for sending comments which has:
<f:ajax event="click" execute="#form" render="#form" listener="#{newsBean.sendComment}" /> and is surrounded by an <h:form>. When button is clicked, NewsBean.init() is always called.
My bean scope is view. Is this a valid behavior (calling always init())? How can I prevent always calling init()?
A preRender listener is always invoked on pre render event, regardless of if it's an initial request or a postback request. Every single request has a render response phase, regardless of if it's a normal request or ajax request. So this behaviour is by specification. You need to check yourself in the listener method if it's a postback request or not by checking FacesContext#isPostback().
public void sendComment() {
if (!FacesContext.getCurrentInstance().isPostback()) {
// ...
}
}
The <f:event type="preRenderXxx"> (where Xxx can be View or Component) is by the way in essence a "workaround approach" for the functional requirement of being able to invoke a bean action method after the view parameters are been processed on the initial request. In the upcoming JSF 2.2 a new <f:viewAction> tag will be introduced which should do exactly the job as intented:
<f:viewAction action="#{newsBean.sendComment}" />
This tag supports an onPostback attribute which already defaults to false:
<f:viewAction action="#{newsBean.sendComment}" onPostback="false" />
JSF 2.2 will be released the first quart of 2012. Snapshot releases of JSF 2.2 are currently already available.
I guess your <f:event> tag is put inside the <h:form> tag. Hence, when you click the ajax button, it re-render the whole <h:form> component which results in the preRenderComponent event being triggered again.
I think what you should use is PreRenderViewEvent.

JSF2: Is there any way to use a4j:param with rich:select or h:selectOneMenu

Is it possible to use with dropdown menus or is it also dependent on the parent object implementing ActionSource as the f:setPropertyActionLister is?
Ideally I would have done something like the following:
<h:selectOneMenu value="#{myCustomBean.selectedItemIndex}">
<f:selectItems value="#{adminLetterAdminBean.missingSettings}" var="n" itemValue="#{n.id}" itemLabel="#{n.name}"/>
<f:setPropertyActionListener value="42" target="#{adminLetterAdminBean.someProperty}" />
<a4j:ajax />
</rich:select>
However this does not work because h:selectOneMenu does not implement javax.faces.component.ActionSource. The page does not render and it gives me a friendly stack trace to tell me about this dependency.
Not seeing anything in the Richfaces documentation about this constraint, I tried the following:
<h:selectOneMenu value="#{myCustomBean.selectedItemIndex}">
<f:selectItems value="#{adminLetterAdminBean.missingSettings}" var="n" itemValue="#{n.id}" itemLabel="#{n.name}"/>
<a4j:param assignTo="#{adminLetterAdminBean.someProperty}" value="42" name="randomRequestParamName"/>
<a4j:ajax />
</rich:select>
This does not blow up, but it also does not set the property. I was wondering if there is a set a (or multiple) properties in a similar fashion.
a4j:param can only be nested inside an action component such as a4j:commandButon, a4j:commandLink and a4j:jsFunction. You can also use it with the standard button/link components.
I had a similiar problem. My page has to transfer information about the autocomplete before the autocomplete request is done. I achieved this by using jsFunction. My autocomplete looks like:
<rich:autocomplete mode="ajax" showButton="true" value="#{conf.fieldValue}"
autocompleteMethod="#{BackingBean.search.autocomplete}"
minChars="3" onfocus="sendInfo('#{conf.label}')">
</rich:autocomplete>
Depending on conf.label (conf is a forEach variable) different data is fetched by the backing bean in the autocomplete method.
The transfer of this information is done by jsFunction (just after the autocomplete declaration):
<a4j:jsFunction name="sendInfo">
<a4j:param name="param1" assignTo="#{BackingBean.search.currentAutocomplete}"/>
</a4j:jsFunction>
Just, when the user puts the focus on a specific autocomplete "sendInfo" is executed with one parameter which is bound to the backing bean.

Resources