0

I have some jsf-code with a tag that is re-rendered by an ajax call. It contains something like

<h:outputScript>alert("Gotcha")</h:outputScript>

but this is only executed on first load, not on an ajax induced partial render.

This is but a minimal example, what I'm really trying to do is to trigger some server-generated javascript right after the ajax-call has returned, something like

<h:outputScript>#{scriptBean.getScript()}</h:outputScript>

I've seen calling .trigger("click") that is in javascript code returned from an ajax call, Asynchronize ajax calls and javascript code, how to run call some Javascript code with jQuery as soon as element loads to page by Ajax? and Running javascript code called by AJAX, but neither questions nor answers look like they address my question, least not without some additional hint or explanation.

And because I want to keep things small and simple, and because I could avoid anything above jsf:core (mostly), I'd prefer solutions that avoid using yafl (== yet another fancy library).

Edit: as for the comment from @BalusC I post more context:

<composite:implementation>
    <h:form id="${cc.attrs.imgId}" styleClass="small" onchange="alert('Gotcha0');">
        <f:event type="postAddToView" listener="#{mBean.register}" />
        <f:event type="preRenderView" listener="#{mBean.init}" />
        <f:attribute name="flav" value="#{cc.attrs.flav}" />
        <h:graphicImage width="${cc.attrs.width}" id="${cc.attrs.imgId}"
            onclick="if (event.isTrusted) this.nextSibling.value=mods(event);"
            onmouseover="aa=this.id" alt="not found"
            onchange="alert('Gotcha1');"
            value="images/img?#{cc.attrs.flav}=#{mBean.getNextCount()}&amp;imgId=#{cc.attrs.imgId}">
            <f:ajax event="click" execute="@form"
                onevent="function(data) { if (data.status === 'success') { 
                console.log('HiHo'+data.responseCode+'\n\n'+ data.responseText+'\n\n'+data.responseXML);
                me=window.document.getElementById('#{cc.clientId}:#{cc.attrs.imgId}:#{cc.attrs.imgId}');
                me.nextSibling.nextSibling.value=0;
                me.nextSibling.value=0;
                me.myfunc=function(event)
                 {
                 console.log('keyCode='+event.keyCode+' mods='+mods(event)+'/'+this.nextSibling.id);
                    this.nextSibling.value=mods(event);
                    this.nextSibling.nextSibling.value=String.fromCharCode(event.keyCode);
                    this.click();
                 }; }; }"
                listener="#{mBean.handleEvent}" render="@this">
            </f:ajax>
        </h:graphicImage>
        <h:inputHidden id="m" value="#{mBean.keyX}" />
        <h:inputHidden id="k" value="#{mBean.key}" />
    </h:form>
    <h:outputScript>alert("Gotcha2")</h:outputScript>
    <h:outputScript>var i=0;window.document.getElementById('#{cc.clientId}:#{cc.attrs.imgId}:#{cc.attrs.imgId}').myfunc=function(event)
     {
     aa='#{cc.clientId}:#{cc.attrs.imgId}:#{cc.attrs.imgId}';
     this.nextSibling.value=mods(event);
     this.nextSibling.nextSibling.value=String.fromCharCode(event.keyCode);
     this.click();
     };
     </h:outputScript>
</composite:implementation>

"Gotcha2" shows up only at load time, once for each instance of the composite, but not when the component is re-rendered via ajax calls.

"Gotcha0" and "Gotcha1" are completely ignored.

The "HiHo" shows up for every ajax-call on the component, but I would like the function to fire only when the component is rendered, which is a subtle difference, because I might manipulate the render-list on server side, like

  private void addToRenderMap(String obj) {
    FacesContext context = FacesContext.getCurrentInstance();
    Collection<String> renderIds = context.getPartialViewContext().getRenderIds();
    renderIds.add(obj);
  }

or even remove the calling component from the list. (For example, for keypress "i", I want to only show image information in some other component and avoid unnecessary re-sending of the image data.)

Edit2: I see that onchange really is more a onvaluechange for fields that take input, so it's not a big surprise that this part of the code is ignored.

Community
  • 1
  • 1
Gyro Gearloose
  • 1,056
  • 1
  • 9
  • 26
  • @BalusC you got me there, thanks for the hint. NO, obviously this would only render the h:form. There was a reason, though, to put those things outside of the form, but I can't remember. Will do some experimentation. – Gyro Gearloose Feb 07 '16 at 18:18
  • @BalusC right you are, thanks a lot. when I put the h:outputScript just before the end of the h:graphicImage, it works! Should I delete the question? – Gyro Gearloose Feb 07 '16 at 18:32
  • @BalusC, sad, so this is only working by accident. So what is the right way to do it???? – Gyro Gearloose Feb 07 '16 at 18:39

0 Answers0