Access all ajax UIComponents passed by execute attribute in backing bean? - ajax

The following code is a simple form used with ajax component:
<h:form id="loginform">
<h:inputText id="username">
<f:ajax event="blur" execute="loginform:username loginform:loginbutton" ... />
</h:inputText>
<h:inputText id="password">
<f:ajax event="blur" execute="loginform:password loginform:loginbutton" ... />
</h:inputText>
<h:commandButton id="loginbutton" value="login" action="#{indexBean.authentication()}" />
</h:form>
I understand that execute attribute is a space-separated List of IDs for components that should be included in the Ajax request.
I can access the source component at backing bean with AjaxBehaviorEvent.getComponent() method, but how to access the rest of components?

It's available by PartialViewContext#getExecuteIds().
FacesContext context = FacesContext.getCurrentInstance();
Collection<String> executeIds = context.getPartialViewContext().getExecuteIds();
// ...
You can then use UIViewRoot#findComponent() to find component by client ID.
for (String executeId : executeIds) {
UIComponent component = context.getViewRoot().findComponent(executeId);
// ...
}

Related

Ajax request and attributes

I am trying this tutorial which describes how to set attributes into server call and how to analyse the attributes on backing bean;
<h:commandButton id="submit"
actionListener="#{userData.attributeListener}" action="result">
<f:attribute name="value" value="Show Message" />
<f:attribute name="username" value="JSF 2.0 User" />
</h:commandButton>
I googled a lot but most examples show how to set attrs for synch-ed calls not the asynch-ed ones :S So my question is ... how to send attributes on server if that would be the ajax call and how to get them on backing bean (see suggestion A code snippet)?
suggestion A :
<h:commandButton id="submit"
actionListener="#{userData.attributeListener}" action="result">
<f:ajax>
<f:attribute/>? how to
</f:ajax>
</h:commandButton>
and if there is a good tutorial concerning to this question please do share the link :)
Thanks
OK I just wrote a test which sets attributes out the ajax block as :
<h:commandButton id="submit"
actionListener="#{userData.callWithAttributes}" action="result">
<f:attribute name="a" value="#{testa}"/>
<f:attribute name="b" value="#{testb}"/>
<f:ajax .../>
</h:commandButton>
...and on the backing bean
...
public void callWithAttributes(ActionEvent e){
String a=(String) e.getComponent().getAttributes().get("a");
...
}
...
Seems like it's working fine :) So attributes should be placed into event-making component block - the h:commandButton in this particular case...
To set two properties in backing bean you can use f:setPropertyActionListener
<h:commandButton action="#{bean.method}">
<f:setPropertyActionListener value="#{testA}" target="#{bean.valueA}/>
<f:setPropertyActionListener value="#{testB}" target="#{bean.valueB}/>
</h:commandButton>
or with EL method argument support:
<h:commandButton action="#{bean.method(testA, testB)}"/>

Making h:panelGroup clickable, and send back repeated variable

I need to make a panelGrid (one of man that are populated from a list of objects) clickable, and then send the item associated with it to the backing bean.
My HTML so for:
<ui:repeat var="searchItem" value="#{bean.filteredSearchItems}" varStatus="searchResult">
<h:panelGrid>
<!-- I get some info here from the searchResult object -->
</h:panelGrid>
<f:ajax event="click" listener="{bean.clickFlight}" />
<f:param name="lfi" value="#{searchResult.index}" />
</ui:repeat>
I know that (in my backing bean) I need a function called clickSearchItem() that can handle the ajax call, so to test all of this, I did the following in my backing bean:
public void clickFlight()
{
HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
String lfi = req.getParameter("lfi");
if (lfi == null)
log.info("LFI WAS RETURNED AS NULL :(");
log.info("HOPEFULLY AN INDEX OF SOME SORT!: " + lfi);
}
Nothing is getting logged - the click doesn't register. Has anyone else had this problem? Does anyone know how to solve it?
The <f:ajax> needs to be nested into a component implementing ClientBehaviorHolder. If you intend to use <h:panelGrid> (which generates a HTML <table>) for that, then you should be nesting the <f:ajax> in the component itself.
<h:panelGrid>
<f:ajax event="click" listener="{bean.clickFlight}" />
<!-- I get some info here from the searchResult object -->
</h:panelGrid>
The <f:param> is only recognized by renderer of <h:outputFormat> and <h:commandXxx>. Provided that you're targeting a Servlet 3.0 compatible container (Tomcat 7, Glassfish 3, JBoss 6/7, etc) which thus supports EL 2.2, then you can just pass it as method argument instead:
<h:panelGrid>
<f:ajax event="click" listener="{bean.clickFlight(searchResult.index)}" />
<!-- I get some info here from the searchResult object -->
</h:panelGrid>
you can even pass the whole object if preferred:
<h:panelGrid>
<f:ajax event="click" listener="{bean.clickFlight(searchResult)}" />
<!-- I get some info here from the searchResult object -->
</h:panelGrid>
An alternative, if you need <f:param> per se, would be to use <h:commandLink> instead.
<h:commandLink>
<f:ajax event="click" listener="{bean.clickFlight(searchResult)}" />
<f:param name="lfi" value="#{searchResult.index}" />
<h:panelGroup>
<!-- I get some info here from the searchResult object -->
</h:panelGroup>
</h:commandLink>

Passing <p:inputText> values to Bean using ajax

I am having the h:inputText which having a text and by ajax request how can i send it's values to bean class and the values will be validated in further action begin at bean class ..
view page code is
<h:form>
<p:panel id="panel" header="Login Panel" style="margin:0 auto;width:350px;margin-top:15%;">
<p:panelGrid columns="3" id="pgrid1" styleClass="theme" >
<p:outputLabel value="User Name:" />
<p:inputText id="name" value="#{loginBean.name}" required="true" requiredMessage="Name is required">
<f:ajax event="blur" render="label" listener="loginBean.validateName" ></f:ajax>
<!--Here the ajax event working properly but how can i get the inputText value when ajax event is invoked-->
</p:inputText>
<p:message for="name" style="color: red;" />
</p:panelGrid>
<p:commandButton type="Submit" value="Submit" action="#{loginBean.validate}" update="pgrid1" />
</p:panel>
My Bean class Code is :
public void validateName(AjaxBehaviorEvent e)
{
//Here i need inputText value..how can i handle this task..!!
}
JSF has already set the #{loginBean.name} value at that moment. Just access it directly.
public void validateName(AjaxBehaviorEvent e)
{
System.out.println(name); // Look, JSF has already set it.
// ...
}
You've by the way an EL syntax error in <f:ajax listener> which causes the listener method never to be invoked, but I'll bet it to be just carelessness during preparing the question as you mentioned that it is "working properly". In the future questions, please edit code in the real development environment and copypaste real working code instead of blindly editing the code in the question editor.

JSF 2: access selected value of selectOneMenu in a form BEFORE submit

VIEW
<h:form id="main_form">
<p:inputText id="title" required="true" label="Title" value="#{myBean.myLink.title}" immediate="true" />
<p:selectOneMenu id="scope" required="true" label="Scope" value="#{myBean.myLink.scope}" immediate="true" >
<f:selectItem itemLabel="Please choose" itemValue="" />
<f:selectItems value="#{myBean.availableScopes}" id="selScope"/>
</p:selectOneMenu>
<p:inputText id="link" required="true" label="URL" value="#{myBean.myLink.link}" immediate="true">
<p:ajax event="blur" update="msgLink" listener="#{myBean.checkUrl}" />
</p:inputText>
... msgLink and other (required) elements
... submit button
</h:form>
Managed Bean
#Component("myBean")
#Scope("session")
public class MyBean implements Serializable {
private Link myLink;
private Map<String, String> availableScopes;
public MyBean() {
this.availableScopes = new HashMap<String, String>();
this.availableScopes.put("Intranet", "Intranet");
this.availableScopes.put("Internet", "Internet");
}
// setter/getters etc.
public void checkUrl() {
System.out.println(myLink.getTitle()); // works
System.out.println(myLink.getScope()); // DOES NOT work
System.out.println(myLink.getLink()); // works
}
}
I want to check the URL depending of the selected scope before submitting the form. But the called method can access the inputText values of the object. Not the value chosen in selectOneMenu.
I have tried it with getExternalContext().getSessionMap().get("scope") but the SessionMap is null at that time.
Any chance to access the selected value of the combo box?
Thanks
Jim
The <p:ajax> (and <f:ajax>) inside an UIInput component executes/processes by default the current UIInput component (#this) only, not others.
If you want to execute/process all those UIInput components when the listener method is to be invoked, then you should specify that as such in <p:ajax process> (or <f:ajax execute>) attribute:
<p:inputText id="title" ... />
<p:selectOneMenu id="scope" ... >
...
</p:selectOneMenu>
<p:inputText id="link" ...>
<p:ajax process="title scope link" ... />
</p:inputText>
Unrelated to the concrete problem, I wonder how all those immediate="true" attributes are useful in this context. Are you certain you need them?

Invoke aciton method with input value as parameter

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.

Resources