How to pass a parameter value to a4j:jsFunction - ajax

On my page I have a button that opens a list of items in a popup. When I select 1 item in the list, I want to pass the id of the item to the backingbean of my first page. Is it possible? It tried to do it with a4j:jsFunction and a4j:param but it does'nt work.
This is my code:
page 1:
<a4j:jsFunction name="renderGuarantor" render="guarantor" actionListener="#{prospectDetail.setNewGuarantor}">
<a4j:param name="param1" assignTo="#{prospectDetail.newGuarantorId}" />
</a4j:jsFunction>
popuppage:
<h:outputLink value="" onclick="window.opener.renderGuarantor(#{applicant.deposit_id});window.close();">
<h:graphicImage style="padding:0 1px; border:0" value="${path.staticRootUrl}images/confirm.gif" alt="${msg.applicantslist_select}" title="${msg.applicantslist_select}"/>
</h:outputLink>
And this is the backing bean code for the first page
private Integer newGuarantorId;
public void setNewGuarantor() {
guarantor = newGuarantorId;
}
public Integer getNewGuarantorId() {
return newGuarantorId;
}
public void setNewGuarantorId(Integer newGuarantorId) {
this.newGuarantorId = newGuarantorId;
}
When selecting in the popup the method in my backingbean is called, but newGuarantorId is null and setNewGuarantorId is never called.
Is there a solution to my problem?

Hmm.. thats strange, nothing looks wrong..Not an answer to your question but try this workaround - instead of assigning the value to guarantorId, keep the param as <a4j:param name="param1"/> and in the actionListener method retrieve this param1 from the request as String param1 = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().‌​get("param1");.
And then convert this param to int and utilize it further. That should work

Try switching from actionListener to action:
<a4j:jsFunction name="renderGuarantor" render="guarantor" action="#{prospectDetail.setNewGuarantor}">
<a4j:param name="param1" assignTo="#{prospectDetail.newGuarantorId}"/>
</a4j:jsFunction>
Here is recommended reading on the topic: a4j:jsFunction

I think you can try this:
<a4j:jsFunction name="renderGuarantor" render="guarantor"
actionListener="#{prospectDetail.setNewGuarantor(prospectDetail.newGuarantorId)}" />
And in your Managed bean, define the setNewGuarantor method as following:
public void setNewGuarantor(int newGuarantorId) {
guarantor = newGuarantorId;
}

Related

JSF Displaying Text in modal if INSERT operation was successful

What is the correct way to return a value from a method in a managed bean indicating a successful SQL DML operation such as INSERT or UPDATE
Based on the tutorials and some blogs I read online, it says that a good practice in returning values from a method contained in a ManagedBean is a String value of a facelet or the .xhtml page
(in other words, a view) to redirect to a webpage.
Like this.
Original version:
#ManagedBean(name="myBean")
public class MyBean{
public String register(){
String SQL = "INSERT INTO myTable(col1,col2) VALUES(?,?);
PreparedStatement ps = connection.prepareStatement(SQL);
ps.setString(1,someStringVariable1);
ps.setString(2,someStringVariable2);
ps.executeUpdate();
return "index"; //pointing to index.xhtml
}
}
How about if i want to know if the executeUpdate() method was successful?
I thought I'd just change it to something like
Modified version:
public int register(){
int isSuccessful = 0;
try{
String SQL = "INSERT INTO myTable(col1,col2) VALUES(?,?);
PreparedStatement ps = connection.prepareStatement(SQL);
ps.setString(1,someStringVariable1);
ps.setString(2,someStringVariable2);
isSuccessful = ps.executeUpdate();
}
return isSuccessful;
}
However, on the modified version I returned an int which I don't see as correct as per how JSF should work with ManagedBean (Please correct me if i'm wrong)
I asked because say I have a Twitter Bootstrap modal which has the following.
<div class="modal-body">
<h:form>
//....some code here...
<h:commandButton value="Submit" action=#{myBean.register()}
<h:outputText value=" #{myBean.whatToPutHere_ToKnowIf_addData()wasSuccessful}" />
</h:form>
</div>
I need to be able to show within the modal div that register() execution was successful.
What is the simplest and correct way to accomplish that?
I read somewhere that AJAX will help but right now, I have very little knowledge of AJAX so maybe a simple solution to this is better.
I'd appreciate any help.
Thank you.
You can use a bean variable:
#ManagedBean(name="myBean")
public class MyBean {
private boolean isSuccessful = false;
public boolean isSuccessful() { return isSuccessful; }
public String register(){
isSuccessful = ...
}
}
and in your xhtml
....
<h:commandButton value="Submit" action="#{myBean.register()}" />
<f:ajax execute="#form" render="outtext" />
</h:commandButton>
<h:panelGroup id="outtext">
<h:outputText value="any Text" rendered="#{myBean.successful} />
</h:panelGroup>
</h:form>

Is it possible to get a SqlDataSource parameter from the ViewState in asp.net web forms?

I have a SqlDataSource defined in my aspx file that I use to call a StoredProcedure. It takes a hiddenField as its control parameter.
<asp:HiddenField ID="input" runat="server" />
<asp:SqlDataSource ID="source" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="sp" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:ControlParameter ControlID="input" Name="input" Type="String" />
</SelectParameters>
</asp:SqlDataSource>
Is there a way I can grab that parameter from the ViewState instead? Preferably while keeping the datasource definition in the aspx file.
The solution in your case is very easy. Just create your own class inherit it from Parameter and override Evaluate method.
[DefaultProperty("ViewStateKey")]
public class ViewStateParameter : Parameter
{
public string ViewStateKey
{
get
{
return (string)ViewState["ViewStateKey"] ?? string.Empty;
}
set
{
if (ViewStateKey == value)
return;
ViewState["ViewStateKey"] = value;
OnParameterChanged();
}
}
protected override object Evaluate(HttpContext context, Control control)
{
if (control == null || string.IsNullOrEmpty(ViewStateKey))
return null;
return ViewState[ViewStateKey];
}
}
After that you will be able to use your parameter like following (just remember to register it at the top of your page or in web.config):
<asp:SqlDataSource ID="source" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="sp" SelectCommandType="StoredProcedure">
<SelectParameters>
<my:ViewStateParameter Name="input" Type="String" ViewStateKey="input" />
</SelectParameters>
</asp:SqlDataSource>
And your parameter will get its value from viewstate by key input.
I dont feel that the code for ViewStateParameter is of the first class. Maybe you will want to decorate it with more attributes and/or extra parameter checks with assertions.
I have similar problem. I dont want to use hidden fields to bind data source parameters because of security reasons.
I have googled one work-around - use asp:label instead of hidden field (make sure Visible=false). And then your label goes to view state and you can bind label to data source parameters.

Ajax for valueChangeListener

I'm using the p:ajax listener to handle value change events (because valueChangeListener is launched on form submit):
<p:ajax event="change" listener="#{bean.onNameChanged}"/>
Handle method:
public void onNameChanged(final AjaxBehaviorEvent event)
The problem is, I can't find in AjaxBehaviorEvent nor its class hierarchy the place to read the old value of the input. Neither could I find hint in google, how to get the old value...
How to access the old value in the p:ajax onChange event?
The problem is, I can't find in AjaxBehaviorEvent nor its class hierarchy the place to read the old value of the input. Neither could I find hint in google, how to get the old value...
Use a valueChangeListener.
Unfortunatelly, valueChangeListener is invoked before p:ajax, so I don't have actual data from forms in that method, so in theory I could use valueChangeListener to remember the old value and then wait for p:ajax to process...
Queue the value change event to the invoke application phase.
public void valueChangeListenerMethod(ValueChangeEvent event) {
if (event.getPhaseId() != PhaseId.INVOKE_APPLICATION) {
event.setPhaseId(PhaseId.INVOKE_APPLICATION);
event.queue();
return;
}
// Do your original job here.
// It will only be invoked when current phase ID is INVOKE_APPLICATION.
}
The ValueChangeListener should work this way:
The view:
<h:form>
<h:inputText value="#{sessionBean.hello}"
valueChangeListener="#{sessionBean.valueChangeListener}">
<p:ajax/>
</h:inputText>
</h:form>
The bean:
public void valueChangeListener(ValueChangeEvent e) {
System.out.println("valueChangeListener invoked:"
+ " OLD: " + e.getOldValue()
+ " NEW: " + e.getNewValue());
}
The above code will print if I change the text field from "hello" to "world":
valueChangeListener invoked: OLD: hello NEW: world
You could try the following:
Implement the value change event in your bean
public void processValueChange(ValueChangeEvent e){
//foo the bar
}
Define a valueChangeListener on your selection component
<p:selectOneMenu value="#{yourBean.value}" onchange="submit()" valueChangeListener="{#yourBean.processValueChange}">
The key piece there is the submit() bit that processes the enclosing form on change of the value. You can then getNewValue() and getOldValue() as necessary.
EDIT: Now that I think about it, I see no reason why you cannot leave your setup as-is and simply define the valueChangeListener. It should still be processed during the change event in the <p:ajax/>, in fact, it will be processed before the listener for the ajax event itself.
you can use this:
public void onNameChanged(AjaxBehaviorEvent event)
{
String myVal = (String) ((UIOutput) event.getSource()).getValue();
System.out.println("myVal: " + myVal);
}
Workaround is possible (tested with Primefaces 10):
<p:inputText id="name" value="bean.name">
<p:ajax event="valueChange" update="name"
listener="#{bean.onNameChanged}"
onstart="cfg.ext={params:[{name:'oldValue', value:'#{bean.name}'}]};"/>
</p:inputText>
update="name" is important, to get each time the new value into the javascript event handler.
Bean Method:
public void onNameChanged(final AjaxBehaviorEvent event) {
String oldValue = getFacesContext().getExternalContext().getRequestParameterMap()
.get("oldValue");
//Do with oldValue, whatever you want
}

JSF 2: page redirect after ajax call

I'm stuck in a navigation case problem similar to this one.
In a few words, I'm trying to redirect navigation from one page to another, using an ajax rendered h:commandLink.
Here's the backing bean
#ManagedBean
public class StartBean {
public void search(){
FacesContext
.getCurrentInstance()
.getExternalContext()
.getFlash()
.put("result", "hooray!")
;
}
public String showResult(){
return "result?faces-redirect=true";
}
}
and the starting page
<h:body>
<h:form prependId="false">
<h:commandButton value="Click" action="#{startBean.search}">
<f:ajax execute="#this" render="#form"/>
</h:commandButton>
<br/>
<h:commandLink
action="#{startBean.showResult()}"
rendered="#{flash.result != null}"
value="#{flash.result}"
/>
</h:form>
</h:body>
whereas result page is just showing a message. Both pages are on web module context root.
It happens that the h:commandLink is correctly displayed after ajax submit, but clicking on it causes a page refresh. It doesn't redirect towards the result page, as expected.
After it, if page is reloaded (F5), result page is shown. It seems to be a rendering cycle matter.
Any suggestion?
Thanks in advance.
The rendered attribute of all input and command components is re-evaluated when the form is submitted. So if it evaluates false, then JSF simply won't invoke the action. The Flash scope is terminated when the request/response of the search() method is finished. It isn't there in the Flash scope anymore when you send the request of the showResult(). I suggest to put the bean in the view scope and bind the rendered attribute to its property instead.
#ManagedBean
#ViewScoped
public class StartBean {
private String result;
public void search(){
result = "hooray";
}
public String showResult(){
return "result?faces-redirect=true";
}
public String getResult() {
return result;
}
}
with
<h:commandLink
action="#{startBean.showResult}"
rendered="#{startBean.result != null}"
value="#{startBean.result}"
/>
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated

JSF2 Composite component link using ajax

Here is my (simplified) issue :
I've got a page that is using 2 composite components of mine :
- CCSelection
- CCDisplay
In CCSelection, I have a list of values, each one has got a h:commandLink onto.
When clicking on a link, the CCDiaplay component is refreshed using the selected value.
To do this, CCSelection exposes a method attribute that is directly linked on each h:commandLink. The value is given to the method using f:attribute.
In the page backing bean, I've got a method (that is given to CCSelection as an attribute), that sets a member.
CCDisplay gets this value though an cc:attribute via the pages's member's getter.
It works !
Now, I want to ajaxize this behaviour.
I tryed to put an f:ajax for each h:commandLink in CCSelection... but if I put #form or #all in the render attribute, nothing is rendered (but the setter methods are called). If I put the id of the UIComponent (of the Page) to render, I get a nullpointerexception saying that a property is not defined for NamingContainer in CCDisplay. Quite strange because I didn't change anything inside CCDisplay !
I think the solution is to put the f:ajax not inside CCSelection but in Page.
So there may be 2 ways to achieve this :
- CCSelection raises an event f:ajax can manage... but how ?
- Using cc:clientBehaviour for CCSelection. But is it possible to target more that 1 component (I've got many h:commandLink, but I want only 1 event).
- Other ways ?
Here is a pseudo code
page.xhtml
<myComp:ccSelection actionMethod="#{pageBean.select}"
render="#{clientIDHelper.clientId['display']}" />
<h:panelGroup id="diplay" binding="#{clientIDHelper.bindings['display']}">
<myComp:ccDisplay value="#{pageBean.value}" />
</h:panelGroup>
To recover the full clientid of the panel containing the ccDiaplay composite component, I use a clientIDMap technic described here.
PageBean.java
private String _value;
public String getValue() { return _value; }
public void setValue(String value) [ _value = value; }
public void select(String value) {
setValue(value);
}
ccSelection.xhtml
<cc:interface>
<cc:attribute method-signature="void selectAction(String)"
name="actionMethod" />
<cc:attribute name="render" />
</cc:interface>
<cc:implementation>
<t:dataTable value="#{cc.values}"
var="val"
...
>
<h:column>
<t:commandLink actionListener="#{cc.selectionValueListener}"
<f:ajax render="#{cc.attrs.render}" />
<f:attribute name="value"
value="#{val}" />
</t:commandLink>
</h:column>
</t:dataTable>
</cc:implementation>
ccSelection.java
public void selectionValueListener() {
// recover the attribute value
String value = event.getComponent().getAttributes().get("value");
// call the callback method of the page
FacesContext context = FacesContext.getCurrentInstance();
MethodExpression method = (MethodExpression) this.getAttributes().get("actionMethod");
if (method != null)
method.invoke(context.getELContext(), new Object[] {value});
}
I don't think ccDisplay is interressting.
So, if I don't put the f:ajax tag, it works.
When I put the f:ajax with the render pointing to the clientId passed in param, I get an error while loading the page.
If I change the render for #form or #all, the pageBean.select method is called, but ccDisplay is not refreshed.
I think i see a little error in page.xhtml.
See when you created the component cc:display you said:
<cc:attribute method-signature="void selectAction(String)" name="actionMethod" />
That means that a parameter is needed.
But when you call it in page.xhtml you do this:
<myComp:ccSelection actionMethod="#{pageBean.select}"...
And its backing bean method is:
public void select(String value) {
setValue(value);
}
As you see the backing bean is correct, but when you call the component in the page, there is no parameter being passed to the bean, and at the end the value is never set.
I think that might be one of the reasons.
To fix it i think you should pass the value some how:
<myComp:ccSelection actionMethod="#{pageBean.select(???Selected value
???)}"...
OK. It is solved... but I don't like it very much.
You'll think I'm a fool : I solved the problem by removing the <![CDATA surrounding my scripts !
I've already found some issue using CDATA. I don't know if this is a MyFaces bug or something I do the wrong way like putting many h:outputScript blocks with CDATA in composite components but with CDATA, I get errors or not working. Just removing it, it works !

Resources