JSF Ajax - trigger on partially completed field - ajax

I want to implement a "typeahead" type of functionality but for effiency reasons to avoid return a list of possibly thousands of entries, I only want to fire the request to the server when the user has entered at least three characters. I.E. on the 3rd keypress, I want to call my server side search via ajax.
I'm not looking for a full runnable example, just a sketch of how this might be possible, as I'm a bit stumped by it.
I do have a generic ajax handler js file in my app to render the ajax "spinner" so I thought I might be able to hook into event method for status="begin" and somehow abort the request if the input field has less than 3 characters but I don't see how that's possible.
I'm hoping a certain JSF guru might be able to point me in the right direction :)
I'm using standard reference JSF2, no 3rd party libraries...

How about adding a onkeyup="myFunction(event)" to your input
<input type="text" onkeyup="myFunction(event)">
and in js add the following
function myFunction(e){
if (e.target.value && e.target.value.length > 2) {
alert('do some ajax with the value: ' + e.target.value);
}
}
In jsf you can add some hidden input with f:ajax and trigger it from js with somethign like this document.getElementById("myButtonId").click();
Online example

Related

Page not updating after ajax call

I have a custom component (that is, an xhtml file with ui:composition inside) where I have a file upload field. When a file is selected it is uploaded via AJAX like this
<uc:fileUpload
id="#{id}fileUploadComponent"
idSuffix="#{id}fileUploadSuffix"
value="#{fileUpload.docsFilePart}"
accept="#{fieldWrapper.acceptedFileTypes}"
widgetVar="#{id}documentUploadWidget"
nullAllowed="#{!((fieldDef.mandatory and
fieldWrapper.getCurrentFileCount() lt 1) and isSaving)}"
maxSize="#{customField.maxFileSize}" >
<f:ajax listener="#{fileUpload.uploadNewFile(fieldWrapper)}" render="#{localId}fileUploadMain messages"/>
</uc:fileUpload>
Below this upload there's a <div> with the same id as specified in the render attribute of the ajax call, where links for downloading the files are shown. What happens is weird - after a file is selected, it is uploaded, the <div> is updated correctly with a link to the newly uploaded file. However when I click "Cancel" or "Save" on the page, their according actions are called, a correct response is returned to the browser (with status 200) but the browser seems to ignore it - the page is not visually updated or anything...
The custom component is quite big piece of code with not-so-easy-to-rewrite logic so replacing it at this point will be... hard...
One thing to not might be that uploading the file happens in a separate controller, while the main page controller is another one. This is because the separate controller is supposed to handle uploads from the custom component.
I can't really understand what exactly happens, even less why, and I'll appreciate any ideas!
For what it's worth, I am using Mojarra on Wildfly 11 (the one provided by the AS)
As it turns out, the reason is that file uploading via JSF AJAX causes the creation of an iframe called "JSFFrameId" and that frame being set as the target of the nesting form. After the AJAX request completes the target is not removed/cleared thus causing responses to go into that iframe and breaking the view.
At this point I am not sure what causes this, but a workaround for me is to have onevent in the <f:ajax> definition, that clears the form target, like this:
<f:ajax
listener="#{fileUpload.uploadNewFile(fieldWrapper)}"
onevent="function(e){if (e.status == 'complete') { $(e.source).parents('form').attr('target','');}"
render="#{localId}fileUploadMain messages">
I will check what other states may need handling but basically this solves the problem. It may be useful if someone shares their suspicions on what may have caused JSF to leave behind this iframe and not reset the target of the form.

Load data on ajax for Row expander in ExtJs

I am using Sencha ExtJs grid 4.2 . I am using a Expander plugins for my grid and try to load data under expanded region from Ajax. Right now I am using this code to show data on expanding.
plugins: [{
ptype: 'rowexpander',
rowBodyTpl: new Ext.XTemplate(
'<br><img height="31" width="32" src="../upload/patient/thumb/{patient_image}">',
' <p><b>{fname}, {lname}</b></p>',
'<br> {accordian_view}'
)
}],
Here you can see that data is pre populated, but my requirement is to load data on expanding. I am trying hard to find the event or process to do it. But still no luck. If anyone have any idea please share.
Thanks in Advance
You might check out the expandbody event on the RowExpander plugin: http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.grid.plugin.RowExpander-event-expandbody
This event passes not only the row's bound record, but also the expanded element, so you could:
Request data via Ext.Ajax.request({...})
Handle response
Add content to expanded row
One thing to keep in mind, however, is the async nature of this approach. That is, the row is going to expand immediately, regardless of how long the subsequent request takes to come back. So it would probably be a good idea to do something like this instead when handling the expandbody event:
Add "loading" text/icon/whatever into expanded row area
Make Ajax request
Handle response
Replace loading text/icon/whatever with the data returned from the Ajax request
It's likely someone has already done so, but you could also (and I would highly suggest it) wrap this process into a custom plugin of your own that extends the RowPlugin. That way you could use it elsewhere in your app for any grid. If you end up creating a custom plugin, please share it with the community!
EDIT: A quick Google revealed a number of custom plugins that do precisely this. For example: https://github.com/nickbretz/Ext.ux.AsyncRowExpander/blob/master/AsyncRowExpander.js

jQuery Showing an Ajax loader during transmission & Prevent Multiple Submits

I have an app that has several different types of form elements which all post data to the server with jQuery AJAX.
What I want to do is:
Show a loader during AJAX transmission
Prevent the user from submitting twice+ (clicking a lot)
This is easy to do on a one off basis for every type of form on the site (comments, file upload, etc). But I'm curious to learn if that is a more global way to handle this?
Something that's smart enough to say:
If a form is submitting to the server and waiting for a response, ignore all submits
Show a DISABLED class on the submitted / clicked item
Show a loading class on the class="spinner" which is closest to the submit item clicked
What do you think? Good idea? Done before?
Take a look at the jQuery Global Ajax Event Handlers.
In a nutshell, you can set events which occur on each and every AJAX request, hence the name Global Event Handlers. There are a few different events, I'll use ajaxStart() and ajaxComplete() in my code sample below.
The idea is that we show the loading, disable the form & button on the ajaxStart() event, then reenable the form and hide the loading element inside the ajaxComplete() event.
var $form = $("form");
$form.ajaxStart(function() {
// show loading
$("#loading", this).show();
// Add class of disabled to form element
$(this).addClass("disabled");
// Disable button
$("input[type=submit]", this).attr("disabled", true);
});
And the AJAX complete event
$form.ajaxComplete(function() {
// hide loading
$("#loading", this).hide();
// Remove disabled class
$(this).removeClass("disabled");
// Re-enable button
$("input[type=submit]", this).removeAttr("disabled");
});
You might need to attach to the ajaxError event as well in case an AJAX call fails since you might need to clean up some of the elements. Test it out and see what happens on a failed AJAX request.
P.S. If you're calling $.ajax or similar ($.getJSON), you can still set these events via $.ajaxStart and $.ajaxComplete since the AJAX isn't attached to any element. You'll need to rearrange the code a little though since you won't have access to $(this).
I believe you have to do 2 for sure and 3 to improve usability of your app. It is better to keep backend dumb but if you have a security issue you should handle that too.

update the row using ajax in cakephp

i am using cakephp in my project. in this at one section i need to update the particular row onclick of the image. using ajax. i used mootools as javascript library. so please help me how could i do this.
thanks in advance
Simply speaking:
Create a CakePHP controller action that performs the row update.
Determine the URL of the controller action you just created. (ie. /controllername/actionname)
Determine if you need to do a GET or POST request to this URL for it to work.
Put code in your view that attaches an "onclick" event that makes and AJAX (GET/POST) request to the above controller.
CakePHP has a javascript helper that traditionally produced Prototype code, but in v1.3 it is now able to produce code for other Javascript frameworks (such as Mootools, jQuery, etc.)
However, many suggest writing your javascript in javascript (eg. actually using the Mootools framwork), rather than writing your javascript in PHP (like using CakePHP's helper to produce Mootools code).
Either way, in your view you need to have something like: <?php echo $js->link(.. or <script>Moo.. or <a onclick="Moo.. to attach your Javascript to that link.
You may also wish for your controller action to return some sort of response indicating whether or not the row update failed or succeeded. In that case you need to make sure the CakePHP controller action you are calling has a view that outputs this. JSON seems to be the ideal format for this (eg. { success: true }), but you need to remember to turn off Cake's debug output. This response can be captured into a variable by your Mootools code where you can decide what to do with it (eg. displaying an error).
As i know most programmer work with protype.js library.
i am giving you link see
go to there

Hot to implement grails server-side-triggered dialog, or how to break out of update region after AJAX call

In grails, I use the mechanism below in order to implement what I'd call a conditional server-side-triggered dialog: When a form is submitted, data must first be processed by a controller. Based on the outcome, there must either be a) a modal Yes/No confirmation in front of the "old" screen or b) a redirect to a new controller/view replacing the "old" screen (no confirmation required).
So here's my current approach:
In the originating view, I have a <g:formRemote name="requestForm" url="[controller:'test', action:'testRequest']", update:"dummyRegion"> and a
<span id="dummyRegion"> which is hidden by CSS
When submitting the form, the test controller checks if a confirmation is necessary and if so, renders a template with a yui-based dialog including Yes No buttons in front of the old screen (which works fine because the dialog "comes from" the dummyRegion, not overwriting the page). When Yes is pressed, the right other controller & action is called and the old screen is replaced, if No is pressed, the dialog is cancelled and the "old" screen is shown again without the dialog. Works well until here.
When submitting the form and test controller sees that NO confirmation is necessary, I would usually directly redirect to the right other controller & action. But the problem is that the corresponding view of that controller does not appear because it is rendered in the invisble dummyRegion as well. So I currently use a GSP template including a javascript redirect which I render instead. However a javascript redirect is often not allowed by the browser and I think it's not a clean solution.
So (finally ;-) my question is: How do I get a controller redirect to cause the corresponding view to "break out" of my AJAX dummyRegion, replacing the whole screen again?
Or: Do you have a better approach for what I have in mind? But please note that I cannot check on the client side whether the confirmation is necessary, there needs to be a server call! Also I'd like to avoid that the whole page has to be refreshed just for the confirmation dialog to pop up (which would also be possible without AJAX).
Thanks for any hints!
I know, it's not an "integrated" solution, but have you considered to do this "manually" with some JS library of your choice (my personal choice would be jQuery, but any other of the established libraries should do the trick)? This way you wouldn't depend on any update "region", but could do whatever you want (such as updating any DOM element) in the response handler of the AJAX request.
Just a thought. My personal experience is that the "built-in" AJAX/JS stuff in Grails often lacks some flexibility and I've always been better off just doing everything in plain jQuery.
This sounds like a good use-case for using web flows. If you want to show Form A, do some kind of check, and then either move onto NextScreen or show a Dialog that later redirects to NextScreen, then you could accomplish this with a flow:
def shoppingCartFlow = {
showFormA {
on("submit") {
if(needToShowDialog())return
}.to "showNextScreen"
on("return").to "showDialog"
}
showDialog {
on("submit").to "showNextScreen"
}
showNextScreen {
redirect(controller:"nextController", action:"nextAction")
}
}
Then you create a showDialog.gsp that pops up the dialog.
--EDIT--
But, you want an Ajax response to the first form submit, which WebFlow does not support. This tutorial, though, will teach you how to Ajaxify your web flow.

Resources