JSF - How to run javascript expression from code - ajax

Trying to do this programatically
<a4j:commandLink ... onclick="#{rich:component('modalPanelID')}.show()"/>
This doesn't work:
HtmlAjaxCommandLink commandLinkObject = new HtmlAjaxCommandLink();
...
commandLinkObject.setOnClick("#{rich:component('modalPanelID')}.show()");
Any idea why and how to make it work?
Thanx.

Because the expression is never evaluated.
With the first approach when the page is rendered the #{rich:component...} is evaluated by Richfaces and something like the code below is rendered on the page:
document.getElementById('formID:modalPanelID').component.show();
Because you are doing this progammatically you are bypassing this rendering. I would suggest that you just use the rendered javascript from above.
commandLinkObject.setOnClick("document.getElementById('formID:modalPanelID').component.show()");

Related

a4j:commandbutton within f:ajax nested does not execute oncomplete

As you can see below, I have a f:ajax nested in a a4j:commandLink, something similar to what I read here in order to solve a saving-on-db issue.
Now, when I click the commandLink, oncomplete is never call. That means, the modal does not close and the cursor keeps on "waiting" mode. If I remove the f:ajax, oncomplete is called but the saving-on-database comes back.
I have already tried several things but no one actually worked. Does anyway what might be the problem here?
Thanks in advance
<a4j:commandLink value="#{msg.label_accept}"
onclick="this.disabled=true; document.body.style.cursor='wait';"
action="#{backingBeanRef['select']}"
oncomplete="this.disabled=false; document.body.style.cursor='auto';closeModal('modalDocumentationCenter');"
styleClass="btn btn-default btn-einvoice"
render="#this">
<f:ajax execute="inputTitle inputDescription"/>
</a4j:commandLink>
a4j:commandLink has ajax already. So use execute from a4j:commandLink directly. Don't use another ajax tag. You can't (or, for sure, you shouldn't) use both.
Or I you really want to use f:ajax, then use h:commandLink instead of a4j:commandLink.
PS. You can try to use a4j:ajax, but I'm pretty sure the result will be the same as for f:ajax.

How to Trigger an AJAX call in JSF from Javascript and avoid using global functions as callback handlers?

I want to move the JSF AJAX triggering code written with f:ajax, f:event and the h:commandLink (with its action attribute) to Javascript by using the jsf.util.ajax. - Why ? Because to avoid globally written handler functions to handle call backs. We are migrating the JS code to AMD Require JS and JSF isn't playing very well
Previously, the code to trigger AJAX calls from the view XHTML file in JSF was written like this :
<h:commandLink id="elemID" tabindex="-1" rendered="#{something.isEnabled ('showSomeLink')}">
<f:ajax render="#{someBean.getElemId('LinkID')}" onevent="renderAjax" />
<jsft:event type="ajax"> someBean.someMethod(); </jsft:event>
</h:commandLink>
The above markup gets rendered in HTML as follows:
Then, a click event was triggered on this link to execute the AJAX and the action.
The jsft:event was used which behaves similarly to its counterpart f:event.
I do not want to use this because it forces to define JS functions globally. In this case, renderAjax() in the onevent attribute of f:ajax
As you can see, This relies on a globally defined function called renderAjax() as the callback function to execute something and render on the UI side.
The trouble is we are moving into AMD and require JS and we have no scope of defining any globals in our code (we can but we do not want to). Even if we did, this ajax call gets triggered much before Require AMD loads
So I attempted to re-write this ajax call from the client side in JS, inside an AMD module, like this (from the generated HTML snippet's onclick mentioned above)
(Point to note, I did not know how to mention the action attribute in this JS code.)
jsf.util.chain(document.getElementById('elemID'), event,'jsf.ajax.request(\'elemID\',event,{render:\'LinkID\',onevent:renderAjax,\'javax.faces.behavior.event\':\'action\'})');
Once I wrote the above code in JS, I removed the f:ajax (since the render and the onevent attributes came inside the JS code itself ) and the jsft:event from the view, in the XHTML file. Once I removed this, it began causing a continuous reload of the page, as an infinite loop. I had to stop the server and put back the code to its old state.
Next, I thought h:commandLink was the issue and decided to replace h:commandLink with a normally rendered anchor tag via the h:outputLink.
Unfortunately this doesn't have an action attribute. The point is, although the element is rendered,
jsf.util.chain(document.getElementById('elemID'), event,'jsf.ajax.request(\'elemID\',event,{render:\'LinkID\',onevent:renderAjax,\'javax.faces.behavior.event\':\'action\'})');
Since my code with h:outputLink has no action attribute, it doesnt execute the method in the managed Bean.
Suppose I included the h:commandLink, without the jsft:event and the f:ajax, then it causes an infinite page reload.
I even added the action attribute to the h:commandLink after removing the jsft:event and f:ajax . I made it work with the below update.
<h:commandLink id="elemID" tabindex="-1" rendered="#{something.isEnabled ('showSomeLink')}" action="#{someBean.someMethod()}">
<f:ajax />
</h:commandLink>
and then using the following in JS:
jsf.util.chain(document.getElementById('elemID'), event,'jsf.ajax.request(\'elemID\',event,{render:\'LinkID\',onevent:renderAjax,\'javax.faces.behavior.event\':\'action\'})');
So far it works. But the problem is my renderAjax is still globally defined. Now i move my JS function into a require AMD module. The function renderAjax is no longer globally available and I move the jsf ajax code also into my module and access it as:
jsf.util.chain(document.getElementById('elemID'), event,'jsf.ajax.request(\'elemID\',event,{render:\'LinkID\',onevent:_t.renderAjax,\'javax.faces.behavior.event\':\'action\'})');
Note, _t.renderAjax() is now inside a module in Require JS. The Error i get now is _t is undefined. I guess it expects to see only global functions. The fun part is it automatically creates a wrapper function around the code. Is there any way to fix this?
(function(event
/**/) {
jsf.ajax.request('elemID',event,{render:'LinkID',onevent:_t.renderAjax,'javax.faces.behavior.event':'action'})
})
If someone could help me fix this, it would be extremely helpful.
Ok. I figured this out. I'm not sure if this is the right method. But it works.
Remove the following section as its not right to create a dummy link just for the sake of triggering a click event on it (in order to make JSF ajax work). It also forces to define global handler call backs as mentioned above which pollutes the global namespace, prevents the modularization of JS code, makes it imposs to move to AMD:
<h:commandLink id="elemID" tabindex="-1" rendered="#{something.isEnabled ('showSomeLink')}">
<f:ajax render="#{someBean.getElemId('LinkID')}" onevent="renderAjax" />
<jsft:event type="ajax"> someBean.someMethod(); </jsft:event>
</h:commandLink>
Now create a simple XHTML file called ajax.xhtml that serves as a template.
Create another file called needHelp.xhtml that uses the above file ajax.xhtml as the template
Both steps (1) and (2) have been shown in an image below:
http://i61.tinypic.com/2rgypsi.png
In the backing bean, do this:
http://i62.tinypic.com/1037bci.png
This completes the setup. Our Ajax response is now in the JSON format and written to the response stream.
Now, in the required AMD require Module,
define('checkChannel', ['jQuery', 'ajaxHandlers'], function($, ajaxHandlers){
(function checkChannel(){
$.ajax({
url : baseURL+"/needHelp.jsf",
dataType : "json",
type: "POST",
success : ajaxHandlers.renderAjax
});
})();
})
The success handler is used to update whatever DOM element needed, based on the response flags. In this case, it would update the element with id="LinkID", as defined in the original code snippet.
Now, the renderAjax is well wrapped inside an AMD module and is no longer required to be defined globally. Now there is no need to use the and or have dummy links created via to simulate a click and trigger AJAX in JSF. If the view state needs to be maintained, it can always be got and updated in a similar manner.
Also, baseURL is the basehref of your app. For example, if the page
was www.example.com/tool/index.jsf, then the baseUrl would be
www.example.com/tool/. So, the AJAX URL would be
www.example.com/tool/needHelp.jsf
PS: pardon the external image links as stackoverflow did not let me
post pics / more links as i needed atleast 10 reputation to post. I
had to use external images as I had some trouble formatting the code.

jasmine-jquery toBeDisabled not working

I have got following html
<a disabled="disabled"><img alt="First" src="/Content/Images/Grid/disabledFirst.png"></a>
And I run following expect on this html
expect($(element)).toBeDisabled()
where element is the selector for above html. The expect fails. Further investigation lead to following code in jasmine-jquery-1.3.1.js
toBeDisabled: function(selector){
return this.actual.is(':disabled');
},
which for some reason is returning false. I'm sure I'm missing something very basic here but just not able to spot it.
This fiddle shows that jQuery only finds inputs not anchors when using :disabled. It's understandable because the anchor element doesn't have the disabled property

Unexpected result loading partial view into an IE8 DOM using jQuery Ajax

I have a strange result happening when loading a Partial View using jQuery Ajax into the DOM, but only when viewing the result using IE8.
The Partial View in question (for example purposes only) looks like this;
<aside>Example test</aside>
When the result comes back from the Ajax call it appears to look exactly as above. However when viewing the DOM using the developer tools in IE8 the result looks like this;
<aisde/>
Example test
</aside/>
As a result the element is not recognised and the text does not sit within it. Also the style sheet class for 'aside' is not being applied. This only happens in IE8 as far as I can see.
Any one got any suggestions, other than do not use custom tags?
Thanks in advance
You need to make sure the DOM recognizes HTML5 elements. Essentially you will have to do:
document.createElement('aisde');
Have a look at this link. Without creating the element older IE browsers will not see or style the elements.
The common practice around these issues is to load a html5 fix javascript file within a conditional comment block. The script does a createElement on all new html5 node types.
<!--[if lte IE 8]>
<script src="html5.js" type="text/javascript"></script>
<![endif]-->

MonoRail: how to remove prototype validation?

I'm maintaining an application with monorail, and we decided to change the validation method for the Jquery one. So far so good, but... the problem i'm having is that i can't get rid of the reference to the previous validation method which is prototype.
Thing is that a Javascript is always placed after the tag forms i create.
<script type="text/javascript">
if (!window.prototypeValidators) prototypeValidators = $A([]);
var validator = new Validation('form1', {onSubmit:true, focusOnError:true, stopOnFirst:false, immediate:true, useTitles:true});
prototypeValidators['form1'] = validator;
</script>
I haven't been able to find clear documentation about monorail validation methods.
And this turns to produce some errors on the browser like so:
$A is not defined
[Break On This Error] if (!window.prototypeValidators) prototypeValidators = $A([]);
Any help or pointers in the right way for documentation about this or how to remove this kind of validation from monorail, will be greatly appreciated.
Thanks in advance
MetalGeorge
PS. i gotta say i'm fairly new to monorail
You can switch to jQuery generation (default is Prototype as you noted) with the JSGeneratorConfiguration property in the Monorail config. See http://hammett.castleproject.org/?p=238 for reference.
Or you can get rid of form validation generation completely by replacing:
$Form.FormTag("%{action='LoginAction'}")
...
$Form.EndFormTag()
with a regular form tag:
<form method="post" action="$Url.For("%{action='LoginAction'}")">
...
</form>

Resources