Friday, August 23, 2013

view.postScript() only works for certain events on an Xpage

I discovered an undocumented feature today when trying to use the view.postScript() method.  This method (added in 8.5.3) allows you to run client side JavaScript at the conclusion of a block of server side JavaScript.  I discovered this issue, when I moved some code in the onClientLoad event of a Panel from clientside to serverside.   I needed to reference a value on the current document, and run a different function based on the value.

I thought to myself, "no problem, I will just use view.postScript() and it will run fine."   When I test the code, nothing happens.   The script never runs, and there are no errors.  I checked Firebug and the scripts loaded fine, as in I was able to launch them using the JavaScript console.  At that point, I did some googling and didn't find all that much out there on view.postScript().   I found a few articles, but nothing that helped me with my problem.

I then turned to Stack Overflow.  Sometimes, just the act of trying to write a question as clear as possible will cause me to think of the answer before I even post the question, but not this time though.  I went ahead and posted this question.

After I posted I got to thinking that maybe it wasn't my logic, but just that the code was being ignored.   I created a alert message using view.postScript and it still did not work.   I then tried putting that alert in the afterRenderResponse event of the xpage, where I had some other code.   Nothing happened there either. Frustrated, I then started putting the code in all the events, and to my surprise it worked some places and not others.  

Basically, the view.postScript() method only works in certain events.   I do not know why this is, but if I had to guess it has something to do with the JSF lifecycle.

I did some experimenting with the Xpage events and here is what I found.

  1. onClientLoad = nothing
  2. beforePageLoad = XSP error
  3. afterPageLoad = WORKS!
  4. afterRestoreView = nothing
  5. beforeRenderResponse = WORKS!
  6. afterRenderResponse = nothing
I can tell you that it doesn't work in the only Panel event, onClientLoad.  I am pretty sure I have used it with onClick events before, so it does work there.

The bottom line is when you view.postScript(), and you should, be aware that, if it does nothing then you might be using it in a place where it isn't supported.   In that case, first try a simple alert, and if that works then it is your code, if it doesn't then you can't use view.postScript in that event.   In my case, I moved the code to afterPageLoad and it worked great.

4 comments:

  1. When you consider that the render_response phase of the lifecycle sends the markup to the browser, it makes sense that any code intended to affect that markup would have no effect if run during afterRenderResponse: it's too late. beforePageLoad is too early because the component tree doesn't exist yet. Not sure why it wouldn't work in the other events, but probably for similar reasons.

    ReplyDelete
  2. Thanks for Tim!! I figured there were good reasons, I just wish all places where it wasn't available would error instead of do nothing.

    ReplyDelete
  3. I put this in the beforeRenderResponse to do a partialRefreshGet and I get an error.
    view.postScript("partialRefreshGet('#{id:panelAll}')")
    The error says that partialRefreshGet is undeined. Not sure if my syntax is correct but the view.postScript seems to be trying to execute the call.

    ReplyDelete
    Replies
    1. partialRefreshGet() is a method of the XSP object, not the global window object, so you would need to call XSP.partialRefreshGet(), not just partialRefreshGet().

      Delete