i have a button that is calling an agent , and i would like to return to the calling page as the last line of the button.
Is there a way to use context.redirectToPage() in conjunction with "$$PreviousPage" instead of capturing the previous page via a before page load scope variable?
Thanks !
If you just want to 'stay on page' use a partial refresh and eventually the standby control. If you want to get to the previous page you can chain simple actions. Action 1 would be 'run code' action 2 the redirect.
You might want to check your response time. Converting your agent to a Java class will most likely give you better response times
Related
I have a strange thing occurring; as usual, I can't post code, unfortunately, so I'm describing the problem in case anyone can suggest a possible cause.
I have an xpage with a custom control included on it; the custom control handles document locking and changing to edit/read-only modes via links. The document locking is done by setting an applicationScope variable based on the UNID. To make it more friendly for other users on the system, I run a function periodically on the page to check whether the document is locked or not and update a link/label/tooltips appropriately (e.g. if locked by another user, then the "Edit" button is disabled; when the lock is released, it's re-enabled). This is done by calling an "xagent" through a standard, simple dojo-based ajax call.
For some reason, the behavior of the system gets erratic after 45 seconds to a minute. I'm checking the lock status every ten seconds or so, so it's not happening with the first call. I'm displaying a list of records associated with the document; each record is a row in a repeat. When I first go into edit mode, the controls are all displayed as they should be, i.e. editable. If the user changes a particular value with a combobox, it updates the whole row with a partial refresh. When things get erratic, I noticed that the row starts refreshing in read-only mode, which suggests to me that the document is changing edit mode. The only time I knowingly change edit mode is if a "Cancel" or "Save" button is pressed. (The locking mechanism itself doesn't have anything to do with the edit mode.)
It certainly seems like the ajax call I'm making is at the root of this. But I've stripped the xagent and the client-side code down to practically nothing, and it's still happening. I can't see what would be causing this behavior. Can anyone hazard a guess? Thanks....
Maybe check if the server log file has warnings like:
WARNING CLFAD####W: State data not available for /page because no control tree was found in the cache.
If you're seeing those warnings, it could be that the server can no longer find the current XPage page instance in the cache. In that case the page will revert to the initial state, like when the page was first opened. That might be why the document goes to read-only mode.
The session cache of server-side page instances only holds 4 pages when xsp.persistence.mode=basic, or it holds 16 instances when xsp.persistence.mode=file or fileex.
If you load 4 xagent page instances, then that will fill the cache, and it will no longer be able to find the page instance for the current XPage you are viewing. So the XPage will stop performing server-side actions, and partial refresh will always show the initial state of that area of the page.
To avoid that problem, in the xagent page you can set viewState="nostate" on the xp:view tag, so that page instances are not saved for the xagent page, as described here:
https://tobysamples.wordpress.com/2014/12/11/no-state-no-problem/
Or else you can create and reuse one page instance for the xagent, so only one is created. That is, on the first call to the XAgent, have the xagent return the $$viewid value for the xagent page instance (#{javascript:view.getUniqueViewId()}), and then in subsequent requests to the xagent use that $$viewid in the request, to restore the existing xagent page instance instead of creating new instances that will fill the cache. So the subsequent xagent requests will be like so:
/myApp.nsf/xagent1.xsp?$$viewid=!aaaaaaaa!
It's hard to troubleshoot without code, but here are a few thoughts:
How are you checking document locking? Via a client-side JavaScript AJAX call or an XPages partial refresh? If the latter, what is the refresh area? If the former, what is the refresh area you're passing and the return HTML? Does it always occur when you're in edit mode on a row and the check happens, or independently of that? The key thing to check here is what the check for locking is doing - is it checking the server and returning a message outside the repeat, or checking the server and returning HTML that overwrites what's currently on the browser with defaults, e.g. the document mode as read mode.
What network activity is happening between the browser and the server and when? Is something else overwriting the HTML for the row, so resetting the row to read mode.
It's unlikely to be random, the key is going to be identifying the reproduceable steps to identify a common scenario/scenarios and cause.
EDIT
Following on from your additional info, is there a rendered property on the Edit link? If that calculates to false in earlier JSF lifecycle phases, the eventHandler is not available to be triggered during the Invoke Application phase. Because the eventHandler also includes the refreshId, there is no refreshId and refreshMode, so it defaults to a full refresh with no SSJS running. See this blog post for clarification http://www.intec.co.uk/view-isrenderingphase-and-buttons/.
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.
$ 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.
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.
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.
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 :-)
I've set my button to 'Submit'. The XPage is set to stay on the same page if save is successful. How do I create a messagebox to inform user the save is successful?
There are a number of options you can consider. A msgbox is the least desirable.
You could add an information message on top of the form that either fades after a few seconds or on change. The custom control would show when you set a viewScope variable (e.g. viewScope.saveSuccess ) and have a visibility formula for it. It also would register an event listener to hide when a field is altered. You also could consider redirecting to a different page.
This post already asks a similar question to do with how to call a client side script from server side, could be useful.
client message after SSJS routine how?
Here are two examples that I have used as inspiration to create a custom control for error messages and for info messages such as what you are asking for:
http://openntf.org/XSnippets.nsf/snippet.xsp?id=ssjs-form-validation-that-triggers-errormessage-controls
http://lotusnotus.com/lotusnotus_en.nsf/dx/xpages-tip-a-simple-cc-for-prompting-ssjs-messages-to-ui....htm
The easiest way to call csjs after running ssjs is to add code the event handler's onComplete event. The onStart, onComplete, and onError events run client side js before or after your ssjs, but are only executed during a partial page refresh.
The simplest way is to add this line of code (or the CSJS you prefer) in the postSaveDocument event:
view.postScript('alert("Document saved")');
I have a Button that in SSJS send and Email...
Now I would if is possibile show the status of sending of email in real-time to the user:
sending process....
sending Successful or sending error
How Can i call a JS client codice from SSJS routine?
Have you any suggest?
If you are using ExtLib then you can also use the #WarningMessage('messageText') method.
You will need to add a section to the XPage to display the messages. It can be as simple as
<xp:messages id="messages1"></xp:messages>
Once added each call to #WarningMessage will add a line to the messages pane.
8.5.3 introduced a very nice approach:
view.postScript
you may insert any CSJS code you like from the SSJS code.
This is quite straightforward.
1. Add a Hidden Input control on your page, noting the id.
2. In your SSJS use getComponent("inputHidden1").setValue("This is the message")
3. Ensure the Hidden Input control is in the area being refreshed (otherwise the value doesn't get passed back to the browser, so can't be accessed in CSJS)
4. Go to the Source pane and place the cursor on or in the eventHandler that is triggering your SSJS. You need to do this to get to the onComplete event
5. In All Properties panel go to onComplete, add your CSJS there. e.g. alert(dojo.byId("#{id:inputHidden1}").value)
This will run your SSJS and on completion alert the user with whatever code is in the field.
For a demo and demo code, check out my blog post: http://www.intec.co.uk/xpages-calling-client-side-javascript-from-server-side-javascript/
Another way to do it besides Pauls answer is to use a dialog from the extlib, and you can call it from ssjs, put a field in a dialog and set it to a scope value and show the dialog.
I create jsp page using JSF Framework.
If i perform some action(Login), then go to the backend and perform some process and it will return some value.
Here this whole process will be taken some times.
Now that time i want to show processing status (wait or busy status) in Mouse.
That means after i press Login button , i want to show that loading status in cursor...
Similarly, If i do, any action in page, then i need to show the loading status...That is, every action in my application, show the loading status.
Help me.
Thanks for your effort.
If you are submitting a form you could use...
<form onsubmit="document.body.style.cursor='wait'"></form>
Here is a list of allowable cursors with CSS.
You could always set the cursor for either the page or for a component on the page via JavaScript.