I meant to send this to the open mailing list in the first place, so I'm forwarding my original message and Ken's response.
Sorry for the long email, but it should be easy to grok.
I'm trying to get a simple Ajax polling example working, and I'm not having much luck. I think I'm running across two Ajax bugs in mojarra. Here's my markup:
<h:form prependId="false">
<h:commandButton value="Start polling" id="startPollingButton"
onclick="startPolling(this, event, 'pollOutput')"
action="#{user.incrementPollIndex}">
<f:ajax listener="#{user.ajaxListener}"/>
</h:commandButton>
<br/>
<h:outputText value="pollOutput is: #{user.pollIndex}" id="pollOutput"/>
<br/>
<h:commandButton id="stopPollingButton" value="Stop polling" action="#{user.stopPolling}"/>
</h:form>
I have two buttons, one to start polling, and the other to stop. I also have an output that displays a backing bean property (#{user.pollIndex}). When you click the start button, it calls my startPolling JavaScript function. That function starts a timer which repeatedly calls jsf.ajax.request():
<script type="text/javascript">
function startPolling(component, event, renderComponents) {
var pollFunction = function poll() {
jsf.ajax.request(component.id, event, { render: renderComponents } )
}
var timer = window.setInterval(pollFunction, 200);
}
</script>
Bug #1: Ajax listener is not invoked when I call jsf.ajax.request() manually.
Everytime I call jsf.ajax.request() in poll(), the button's action gets called, as I expect. However, the Ajax listener associated with the button is only called when I actually click the button, and not when the poll() function is invoked. I expect the Ajax listener, like the button's action, to be invoked everytime I call jsf.ajax.request(). That seems like a reasonable expectation to me.
After rummaging around in the RI code, I found that I could get mojarra to call the Ajax listener everytime I call poll() if I change the call above to jsf.ajax.request() to this:
jsf.ajax.request(component.id, event, { render: renderComponents, 'javax.faces.behavior.event': 'action' } )
Ugh. That's not very intuitive. Why do I have to do that? I expect the Ajax listener to be called without having to resort to such slight of hand.
Bug #2: Removing components from the tree in an Ajax listener does not remove the component from the page when the Ajax call returns.
When polling is complete, I want to remove the output, so in the Ajax listener I tried two things: 1. set the rendered attribute of the output to false. 2. remove the output component from it's parent's list of components. Neither works. In both cases, the output remains in the page until I do a full page refresh, and then it disappears. The output no longer updates after it's removed (or it's rendered attribute is set to false), but it's still in the page. Note that I am specifying that the output component is rendered after the Ajax call.
If I manually remove a component, or set it's rendered attribute to true, during an Ajax call, I expect that component to disappear when the Ajax call returns, provided of course, that it's one of the components to be rendered when the Ajax call returns.
Are these bugs, or are my expectations out of line?
Thanks,
david