Managed bean not called on a4j:jsFunction - javascript

I have a problem with a a4j:jsFunction (below the snippet) :
<a4j:jsFunction
name="updateVal"
render="panelViewStation"
execute="#all"
onbegin="alert('begin');"
onbeforedomupdate="alert('onbeforedomupdate')"
oncomplete="alert('complete');"
action="#{controller.aMethod}"
actionListener="#{controller.anotherMethod}"
onerror="alert('error');">
<a4j:param name="val" assignTo="#{controller.val}"/>
</a4j:jsFunction>
In my managed bean, I have these methods :
/** action method */
public Object aMethod() {
return "something";
}
/** action listener method */
public void anotherMethod(ActionEvent actionEvent) {
// do something
}
// get/setter for val
This method is called by another js function below :
function processSelectEvent(target) {
alert(target.previousElementSibling.textContent);
updateVal(target.previousElementSibling.textContent);
}
and finally this method is called by a autocomplete element
<rich:autocomplete id="stationId" minChars="3" var="station" inputClass="autoCompleteWidth300" onselectitem="processSelectEvent(event.target);"
fetchValue="#{station.name}"
autocompleteMethod="#{controller.searchStations}"
mode="cachedAjax" required="true" autofill="false" layout="table">
Unfortunately, the feature is not as expected.
When I select an element on the autocomplete list, the function processSelectEvent is called.
The js function "updateVal" is called, but only the "onbegin" javascript.
Other attributes are not called (onbeforedomupdate, oncomplete, onerror) and the managed bean is not called too (action, actionListener).
Any idea to solve my problem ? Thx

Check, please, that a4j:jsFunction is inside a form.
The component sends a request using the standard JSF mechanisms. Note
that this means a JSF form is required.
See also http://showcase.richfaces.org/richfaces/component-sample.jsf?demo=jsFunction&skin=classic

Related

Telling JS when AS's ExternalInterface is ready

SOLVED: I should have added more detail. Even though the External Interface was set up the NetConnection/NetStream objects were not connected to the server. As a result, I couldn't make any calls thru. A very important detail I left out, apologies.
I know that it's proper to have Flash call back to JavaScript when External Interface is ready so I make the call. The JS method gets called correctly but I am unable to then trigger a successful call back to the Flash file. I have to manually set a 1-second timeout to get it to work and I don't understand why. If the External Interface is ready then I should be able to call back to Flash right away, right?
By the way, I'm using SWFObject.embedSWF() to place the Flash file on the page. I've given the file an id and name attributes.
Here's my flash code:
private function init():void // onCreationComplete handler
{
this.setupExternalInterface();
}
private function setupExternalInterface():void
{
if (ExternalInterface.available)
{
ExternalInterface.call("swfIsReady");
ExternalInterface.addCallback("call", makeACall);
}
}
And here's the JSP page:
function swfIsReady(){
setTimeout(flexCall,1000);
}
function flexCall(){
var theApp = getFlexApp(attributes.name);
theApp.call();
}
function getFlexApp(appName)
{
if (navigator.appName.indexOf ("Microsoft") !=-1)
{
return window[appName];
}
else
{
return document[appName];
}
}
This is the only way it works. I thought I could just remove the timeout and call flexCall() directly.
I think you have two little problems in your code :
The first problem is using the call() method which is used in JavaScript to invoke a function.
Try this (I'm not sure that's working but to more see the problem) :
swf_obj.call.call();
but the solution is simply to use another name of your callback function :
swf_obj.make_call();
The second one, is calling ExternalInterface.addCallback() after ExternalInterface.call() which you can just inverse their order to get it working.
So your code can be like this for example :
ActionScript :
private function init(event:FlexEvent):void
{
setupExternalInterface();
}
private function setupExternalInterface():void
{
if (ExternalInterface.available)
{
ExternalInterface.addCallback("make_call", makeACall);
ExternalInterface.call("swfIsReady");
}
}
JavaScript :
function swfIsReady()
{
var swf_obj= swfobject.getObjectById(attributes.name);
if (swf_obj) {
swf_obj.make_call();
}
}
Hope that can help.

XAML: Hyperlink to another ViewPage

I am developing a WinRT application and was wondering if i could link a Hyperlink tag to a JavaScript function or be able to call the view page with NavigateUri? Or if it is possible to use interaction triggers that call the JS by a command.
==Update==
I have been testing different xaml tags from hyperlink to hyperlinkbutton. HyperlinkButton seems to appear and is clickable. it is just the on click function that doesn't seem to get called...
<HyperlinkButton Grid.Row="1" Click="__Title__.OnBuildingClick" Content="Buildingoo"/>
<HyperlinkButton Grid.Row="1" Click="__Title__.OnBuildingClick" Content="Buildingoo" ?
<i:EventTrigger EventName="ClickHyperlink">
<behaviors:EventToScriptBehavior Command="__Title__.OnBuildingClick" />
</i:EventTrigger>
</i:Interaction.Triggers>
</HyperlinkButton>
these are the 2 approaches i have taken. The functino onBuildingClick is only an alert msg but it doesnt get called..
Assuming the webView has a predefined name "currentWebView":
<WebView x:Name="currentWebView" ... />
You can access the control from the codebehind using its name, and then tell the web view to search the DOM for a javascript function by name, and invoke it if the function exists.
To invoke a method by name you will use the C# Method "InvokeScript" and pass 2 parameters:
Param 1: Name of Javascript function
Param 2: Comma Separated List of Arguments in order of Javascript Signature
currentWebView.InvokeScript("nameOfFunction", "myFirstparam, secondParam, thridParam");
Additionally, in order to allow the XAML UI to respond to the Javascript event your Javascript code must call
nameOfFunction(param1, param2, param3){
window.external.notify("This content will be accessible in the next steps NotifyEventArgs e.Value property.")
};
and in the last piece of wiring up the ability to respond to Javascript from C#, you must apply an event handler in the C# codebehind to allow the XAML to be notified what is going on inside the WebControl
// In the Constructor / OnLoaded/ OnNaviagtedTo Event of the code behind
currentWebView.ScriptNotify += new NotifyEventHandler(currentWebView_ScriptNotify);
... then later in the class
private void currentWebView_ScriptNotify(object sender, NotifyEventArgs e)
{
//can access the value included in the notification
var notification = e.Value;
someTextblock.Text = notification;
}
Putting It Together:
<HyperlinkButton x:Name="btnExecuteJavaScript" Grid.Row="1" Click="btnExecuteJavaScript_Click" Content="Buildingoo"/>
public void btnExecuteJavaScript_Click(object sender, RoutedEventArgs e)
{
currentWebView.InvokeScript("OnBuildingClick", "arbitraryParameter, mayNotBeNeeded");
}

RequestContext and Ajax status in PrimeFaces

I need to handle globally ajax responses. Everything works ok, out of the box, when I only want to call normal javascript action without any arguments. Than I can use p:ajaxStatus controll, and application behaves in a correct way.
What I actually now need to do, is to handle situation, when during ajax request there was externalContext.redirect() call. It happens only in one place in application, but it is called from many places.
I was thinking, that I can for instance add callback param in RequestContext. But how can I access this param in javascript?
While watching in firebug, I can see that callbackParam is returned in json response, but how can I access this value in javascript?
It's been added as a property of default args object which is available in oncomplete context.
So, for example
RequestContext.getCurrentInstance().addCallbackParam("foo", "bar");
is available as
oncomplete="console.log(args.foo)"
See also:
PrimeFaces RequestContext showcase
Update: as per the comments, that turns out to fail in <p:ajaxStatus>. I sugges to report it as a bug to PF guys, that the arguments are not available in <p:ajaxStatus oncomplete>. In the meanwhile, you can workaround it with the following script which is loaded by <h:outputScript target="head"> inside the <h:body> (to guarantee that it's loaded after PrimeFaces script):
var originalPrimeFacesAjaxUtilsSend = PrimeFaces.ajax.AjaxUtils.send;
PrimeFaces.ajax.AjaxUtils.send = function(cfg) {
var originalOncomplete = cfg.oncomplete;
cfg.oncomplete = function() {
ajaxStatusOncomplete.apply(this, arguments);
if (originalOncomplete) {
originalOncomplete.apply(this, arguments);
}
};
originalPrimeFacesAjaxUtilsSend.apply(this, arguments);
};
function ajaxStatusOncomplete(xhr, status, args) {
// Do your thing here.
}
In p:ajaxStatus params available via PrimeFaces.ajax.Queue.xhrs
For example:
oncomplete="console.log(PrimeFaces.ajax.Queue.xhrs[0].pArgs.foo)"

Conditionally invoking JavaScript from a bean

How do I conditionally invoke JavaScript from a bean in JSF 2?
I have a class that uses PrimeFaces which uploads user files to a particular folder, but if the user attempts to upload a file with the same name as one that is already present, I want JavaScript in this case to open up a box on the screen asking the user if he wants to overwrite the old file, or cancel the operation. If no file with that name is present, then JavaScript is not called.
I know how to test that a folder has a particular file in it, it is just that I need to know how to invoke JavaScript conditionally.
I would most appreciate any advice on this.
I have looked at variopus resources online, but still cannot get the application to work correctly. basically, this is what I have done, in an included xhtml page I have the following code for the file upload:
<p:fileUpload id="fileUpload" fileUploadListener="#{filters.upload}"
allowTypes="#{filters.uploadTypes}" invalidFileMessage="#{filters.uploadBadType}"
sizeLimit="#{filters.uploadSize}" invalidSizeMessag="#{filters.uploadBadSize}"
update="fileUpload fileTable uploadMessage" description="Select Text File"
disabled="#{filters.disableFileUploadButton}"/>
<!--- Then further in the same file is this: -->
<p:remoteCommand name="remoteCommandOverwrite" actionListender="#{filters.execOverwrite}"/>
The parent xhtml page that includes the above I have the foolowing JavaScript:
<script type="text/javascript">
function popupConfirm() {
var overwrite = confirm('Warning: This will overwrite the existing file - Do you confirm this?');
if (overwrite) remoteCommandOverwrite([{name: overwrite, value: true}]);
}
</script>
In my bean I have the following code in three methods:
public void upload(FileUploadEvent event) {
FacesMessage msg = new FacesMessage("Success! ", event.getFile().getFileName() + " is uploaded.");
FacesContext.getCurrentInstance().addMessage(null, msg);
overwrite = false;
// Do what you want with the file
try {
copyFile(event.getFile().getFileName(), event.getFile().getInputstream());
} catch (IOException e) {
e.printStackTrace();
}
}
public void copyFile(String fileName, InputStream in) {
// Initialization etc.
File file = new File(uploadFull + fileName);
if (file.exists()) {
RequestContext.getCurrentInstance().execute("popupConfirm()");
// Then test to see if overwrite is true or false, and act accordingly
}
// Then I am supposed to get the value of overwrite here:
public void execOverwrite() {
System.out.println("### execOverwrite() ###");
FacesContext context = FacesContext.getCurrentInstance();
Map<String, String> map = context.getExternalContext().getRequestParameterMap();
String soverwrite = (String) map.get("overwrite");
if (soverwrite.equals("true")) {
overwrite = true;
System.out.println("overwrite: true");
}
}
What I am trying to do is first to invoke conditionally the JavaScript function popupConfirm(). On clicking the "Upload" button that is invoked if the codition is true, which is what I want. This is then supposed to call
That works and brings up the confirm() box, but the is never called, so the method execOverwrite() in my bean is also never called, and I cannot pick up the return value and pass it to the code inside the method copyFile(). What is going wrong?
I put this problem on the back burner for about a week, and have just got back to it. I got it to work, and can pass a value back to the bean, but somehow I need to resume execution from the place where JavaScript is called.
To sumarize, my JavaScript contains the following code:
<script type="text/javascript">
function popupConfirm() {
var overwrite = confirm('Warning: This will overwrite the existing file - Do you confirm this?');
if (overwrite) remoteCommandOverwrite([{name: 'overwrite', value: 'true'}]);
}
</script>
And in the xhtml code I have:
<p:fileUpload id="fileUpload" fileUploadListener="#{filters.upload}" ...../>
<!-- Other code -->
<p:remoteCommand name="remoteCommandOverwrite" actionListener="#{filters.execOverwrite}"/>
Then on clicking the file upload button after clicking the choose file button, the code in the JavaScript, as listed above, is executed:
RequestContext.getCurrentInstance().execute("popupConfirm()");
Then on clicking "OK" in the dialog box, this method in the same bean is called:
public void execOverwrite() {
FacesContext context = FacesContext.getCurrentInstance();
Map<String, String> map = context.getExternalContext().getRequestParameterMap();
String soverwrite = map.get("overwrite");
if (soverwrite.equals("true")) {
overwrite = true; }
}
}
where the flag "overwrite" will eventually be tested to see if it is true.
Using various print statements I check that this works. However, the code does not resume executing after encountering the statement: RequestContext.getCurrentInstance().execute("popupConfirm()"); regardless of whether I enter "OK" or "Cancel" in the dialog, which is what i want it to do. It looks as if a callback of some type is required, and would most appreciate some ideas.
According to your tag, you are using PrimeFaces, so there is an easy way to invoke a javascript function from a server side event managed bean method when the browser has completed processing the server response. PrimeFaces gives you a utility class called RequestContext.
public void doActionListenerMethod() {
if (!isValid()) {
RequestContext.getCurrentInstance().execute("MyJSObject.doClientSideStuff()");
}
}
The following will execute the string argument as a Javascript when JSF has finished rendering on the client.

Pass value from javascript in jsp to action class in struts2

how can i pass value from javascript to a java class in struts2?
This is the link similar to what I want.However it does not work for me.
I have tried something like this.
Struts tag for hidden in jsp is
function redirect(id)
{
window.alert("Hello"+id);
document.getElementById('param_ID').value=id;
document.forms["./ListAlgorithmAction"].submit();
}
In my action class I have declared getter and setter for the param_ID.But it returns null.
Kindly help.
Thank you.
You should use like this
<s:hidden id = "param_ID" name="xyz" />
Now you should have a getter and setter for xyz property in your struts action.
You should always have name attribute in tags mapped to attributes in Struts action.
Hope this works.
If the page is not submitting your hidden field, maybe the hidden field is not inside your form element. You can try pass it as a parameter to your url. Try this
function redirect(id)
{
var form = document.forms[0];
var url = './ListAlgorithmAction?param_ID=' + id;
form.action = url;
form.submit();
}
Let me know if this works.
If you want to call an action and return data you should use struts2-json plugin JQuery script for calling action
var abc = $("#abc").val();
$.getJSON('youraction.action', {
variable -name action class : abc,
value to be passed:value,
//and so on
}, function(data) {
//your processing code
}
});
return false;
});
If you want to just call action you may want to use $.ajax in place of $.getJson
If you want to use struts 2-json then you would also need to change your struts.xml i.e
<result name="success" type="json"></result>
It's worth a go
I had a similar issue and resolved it by appending the Action class from JavaScript function and appending the URL parameters as shown below:
<a href="(<%actionClassName%>.action?<%URLParms%>" />

Categories