11

This is my first time asking a question on a forum, since usually my questions have already been asked and answered. I haven't found an answer to this problem that works for me, so here goes:

I'm making an Ajax call in JSF 2.0 like this:

< f :ajax listener="#{myReferenceController.clearRequiredReferenceNumber}"
    onevent="resetFocus" execute="@form"
    render=":resultsForm:ResultsDisplay" />

Everything in the listener works perfectly, and the data is then rendered as expected in the data table that I have in my .xhtml page. The problem is that the Javascript that I call in the onevent seems to be getting called before the rendering is complete, and therefore the process of resetting the focus to a column in my datatable doesn't work, since the datatable is removed and then re-added to the DOM when the Ajax is finished re-rendering.

I'm looking in my Javascript for the status of "success", in hopes that at this point, the rendering would have completed. Alas, this is not the case, and my getElementById (actually dojo.byId) is not finding the element in the datatable. I know my Javascript function works under normal circumstances, since I'm calling this same function in a situation where there is not an Ajax call, and everything works perfectly there.

If I could just avoid rendering the cell in the table that I'm trying to set focus to, that would be great, but my listener is making changes to this cell in the ajax call. I'm at my wits end, so any ideas on this would be very appreciated.

-- in response to Balusc (heard good things about you, btw)

Hmm, I was actually on the right track I think, but still seem to be having troubles. I am checking for "success" and still even in success, am not able to set the focus here. Here's my Javascript function that is checking for "success": This function works in another situation, where it's not attached to an Ajax event.

function resetFocus(data) {
    var theRow = dojo.byId("resultsForm:selectedRow").value;               
    if (data.status == "success") {
        dojo.query('[widgetId]',dojo.byId('theResultsDataTable'))
            .forEach(function(node) {
                var widget = dijit.byNode(node);
                var theId = widget.attr("id")                                             
                if (theId.indexOf(':' + theRow + ':') != -1) {
                    if (theId.indexOf('theOrppoNum') != -1) {
                        widget.focus();
                        widget.attr("isFocused",true);
                    }
                }
            });
    }
}
Michael Gaskill
  • 7,913
  • 10
  • 38
  • 43
james
  • 111
  • 1
  • 1
  • 5
  • This looks like an `oncomplete` javascript method for your ajax request. Sadly, this method is not in the JSF specification (more info about it [here](http://old.nabble.com/Is-there-any-'oncomplete'-method-in-jsf.ajax.request()--td28025156.html)). Alternatively, you could use [PrimeFaces](http://www.primefaces.org/showcase-labs/ui/ajaxifyKeyEvents.jsf) or [RichFaces](http://showcase.richfaces.org/richfaces/component-sample.jsf?demo=ajax&skin=blueSky), these frameworks handle this `oncomplete` method for ajax requests. – Luiggi Mendoza Jul 05 '12 at 19:15
  • If this oncomplete method simply handles the attribute status that the event listener gets passed, I don't think this will help me. Even the "success" status seems to be coming back before the ajax and jsf is finished rendering. I'll look into the prime faces and richfaces avenues though..... – james Jul 05 '12 at 19:33

1 Answers1

24

The function attached to the onevent attribute will actually be invoked three times. One time before the ajax request is been sent, one time after the ajax response is been arrived and one time when the HTML DOM is successfully updated. You should be checking the status property of the given data argument for that.

function onEventFunction(data) {
    var status = data.status; // Can be "begin", "complete" or "success".

    switch (status) {
        case "begin": // Before the ajax request is sent.
            // ...
            break;

        case "complete": // After the ajax response is arrived.
            // ...
            break;

        case "success": // After update of HTML DOM based on ajax response..
            // ...
            break;
    }
}

In your particular case, you thus just need to add a check if the status is success.

function resetFocus(data) {
    if (data.status == "success") {
        // Do your job here.
    }
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Well, the "success" advice turned out to be good. I never doubted you BalusC. Only problem I'm having now is that it's not working in IE, but works fine in firefox. Odd, since I'm using dojo to get at the elements in my javascript - supposed to be cross-browser aware... – james Jul 06 '12 at 12:44
  • Ok, it is definitely not related to dojo in any way. I did a test and ran the same javascript code on an onclick event, without ajax. (of course took out the if data.status=="success") and I put alerts inside my code to show that the datatable is not being seen when IE is re-rendering the table after an ajax call, but IS seeing the datatable elements when there's no ajax call. – james Jul 06 '12 at 15:56
  • Ok, I finally have figured out my issue here! Success was definitely returned correctly in all browsers. After setting a javascript alert for each of the statuses, I saw that the screen flickered just before the success alert. Then, when I clicked "ok", it flickered again. The issue was that dojo was also re-rendering the screen by converting normal html elements into its dojo components. All that was needed was to surround my check for status==success by a dojo.addOnLoad function call. Now, all browsers handle this properly! Thanks for all the help on here. – james Aug 03 '12 at 13:07