Sarah Steffen
Sarah Steffen

Reputation: 15

XPages: execute context.redirectToPage after client side function?

Why does context.redirectToPage behave differently when executed in a view root-event instead of an event handler?

This question came up when I tried to set the language of an xpages application to the language saved in the user profile, once the user is logged in. I use a properties-file with translated strings in a resource bundle, and retrieve the strings like this:

<xp:text value="${langString['WELCOME_TEXT']}" />

When the language is changed and so a different properties-file is loaded, the page needs to be refreshed in order to update those strings. This worked fine when I added a full-refresh event handler to the login button, that executed a server side context.redirectToPage(). No luck with client side refreshes like location.reload or window.location.href=window.location.href (the login-function itself is a client side function though).

But of course the user expects that he is also logged in when he presses the enter key instead of the button after he has entered his credentials. So I added an onkeypress-event to the username and password input fields, and checked for the enter key (if (thisEvent.keyCode==13) dosomething...) before executing the login function.

But now the event handler is called every time a key is pressed and of course I do not want the context.redirectToPage to be executed all the time. Thus I removed the server side event handlers and changed the login function so that it terminated with a partial refresh of the div containing the whole page:

var p = {"execLogin":"true"}; XSP.partialRefreshPost( '#{id:wholePage}', {params: p} );

The parameter sent via the partial refresh now triggers an event in which our context.redirectToPage is executed:

<xp:this.beforeRenderResponse><![CDATA[#{javascript:if (param.containsKey('execLogin') && param.get('execLogin').toString().equals('true')) {
    print("test");
    context.redirectToPage(context.getUrl().toSiteRelativeString(context),true);
}}]]></xp:this.beforeRenderResponse>

The page is refreshed and "test" is printed out, but I still see the old language strings. I have to refresh the page manually again to make the new user language take effect.

Any idea how to execute a genuine full refresh this way, or maybe another way to update the strings retrieved from the property bundle?

Thanks in advance. Regards, Sarah

EDIT

I now have:

<xp:inputText id="cc_login_panel_login_username" styleClass="span2">
<xp:eventHandler event="onkeypress" submit="true" refreshMode="complete">
    <xp:this.script><![CDATA[if (thisEvent.keyCode!=13) {
        return false;
    } else {
        doLogin();
        return true;                                
    }]]></xp:this.script>
    <xp:this.action><![CDATA[#{javascript:context.redirectToPage(context.getUrl().toSiteRelativeString(context));}]]></xp:this.action>
</xp:eventHandler>

Because context.reloadPage() didn't even log me in somehow (strange) I got back to using redirectToPage. The server side event is fired once and at the right time *thumbs up*, but the language properties-bevaviour is still the same.

Upvotes: 0

Views: 4008

Answers (4)

Sarah Steffen
Sarah Steffen

Reputation: 15

Thanks for all the helpful answers, in fact all of them did work, the problem turned out to be my misunderstanding of when the properties-file is loaded. It is loaded in an early phase, long before my new language is set to the sessionScope (that sessionScope variable is then used as a part of the name of the properties-file to be loaded, via the VariableResolver).

Now I use a double full refresh to load the new file. When the login function terminates successfully, it executes:

window.location.href = window.location.href + "?doRefresh=true";

And to the view root element I added the following event:

<xp:this.beforeRenderResponse><![CDATA[#{javascript:
if (context.getUrlParameter("doRefresh")!=null&&context.getUrlParameter("doRefresh").equals("true")) {
    var url = context.getUrl().toSiteRelativeString(context);
    url = url.replace("?doRefresh=true","");
    context.redirectToPage(url);}
}]]></xp:this.beforeRenderResponse>

This is not a very sophisticated solution, but at least it works :-)

Upvotes: 0

Eric McCormick
Eric McCormick

Reputation: 2733

I see you're calling "context.redirectToPage(context.getURL().toSiteRelativeString(context)))" within an xp:this.action tag for the xp:eventHandler.

Try using xp:this.onComplete in place of xp:this.action.

According to the Designer tooltip for the action, the expected return is a string to be passed to the navigation handler. So instead giving the onComplete will execute the redirect command when it's done with the eventHandler group of events.

Event Handler Action Tooltip

Upvotes: 0

Paul Stephen Withers
Paul Stephen Withers

Reputation: 15729

$ is only set on page load, whereas # is set each time during the partial refresh.

I don't think a partial refresh will work at all though. This will refresh the computed field. However, it will need a full refresh to refresh the part of the XPage that includes the properties file. In other words, you would be refreshing the computed field, but using the same properties file.

I wonder if context.redirectToPage or context.reloadPage is somehow going to the same page but with the cached properties files.

If you're always wanting to come back to the same page, a full refresh instead of partial refresh may be the best option.

Upvotes: 1

jjtbsomhorst
jjtbsomhorst

Reputation: 1667

I think this has something to do with using the $ parameter. this tells the runtime to retrieve the language file the first time the current page is created in the back-end. When a user does a refresh it is actualy retrieving a saved version of the page you are viewing.

Upvotes: 0

Related Questions