Getting to scope variables in client side javascript (CSJS) on XPages - xpages

I am setting a viewScope variable in a server side javascript (SSJS) button.
viewScope.put("branchName",doc.getItemValueString("BranchName"))
How can I access that variable on the client side?

If you need to access the viewScope variable from a client side script you can use the xp:scriptBlock tag to setup a number of global javascript variables.
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[var myVar = #{javascript:viewScope.get("scopeVar")}]]></xp:this.value>
</xp:scriptBlock>
The main problem with this method is that the inner server side javascript is only computed when that element is initially rendered or when a partial refresh is performed on the element so there is no guarantee that the client side JS variable is set to the correct value.

You can't access viewScope Variables directly, but you could bind it to a hidden field
then access that value via csjs
XSP.getElementById("#{id:inputHidden1}").value
There are other ways to access it also, using something like rpc or an ajax request.

use the below code:
var value = "#{javascript:viewScope.variablename}"

I would take a look at the JSON RPC included with the extension library. This component will allow you to define a SSJS function that may/may not accept arguments. Let's say you add the RPC with an ID of myRPC and a method called getViewScopeVar that accepts a single String argument and returns the value of the viewScope variable with the name that you include as the argument. You can then call that method like:
myRPC.getViewScopeVar("branchName")
This is the easiest most effective way to interact with server side elements from client side javascript. Plus it gives you the option of all the required methods being in one place as long as you place that RPC on a strategic custom control (i.e. like a layout custom control that every xpage is based off of).

If you need frequent updates you can use the Ajax service from the extension library.

Related

XAgent breaks previous navigation

If I use
context.redirectToPrevious()
It works great, but If I call an xagent with or without state between opening the document and doing a close of the document. I end up navigating to the xagent.
And If I go directly to the view behind I loose opened categories in the view.
Is there a way to block an xpage to end up in the navigation/history tree?
There are two approaches that would work.
The first is to use client-side JavaScript to open the XAgent. How you handle that will depend on whether there are values set in the browser that you are passing to sessionScope for the XAgent to use. If not, you can just use client-side JavaScript to open the relevant XAgent page. If you do need values, there are two options:
Pass them as query string parameters to the XAgent instead of storing them as sessionScope variables.
Perform a partial refresh to store the values in sessionScope and open the XAgent page via client-side JavaScript either in the onComplete() event (will trigger every time) or using view.postScript(), passing the relevant CSJS as a string (will only trigger if validation is successful).
The second is to set the previous page in the beforePageLoad event and then use that value in context.redirectToPage().

How to obtain information of a field or variable on the Client side

I am using the Receipts page (IN301000) for reference purposes:
I would like to be able to obtain a field's information on the client side with the GetElementByID() method.
When I inspect the field, and identify the rendered ID, I obtain data:
However, if I refresh the page and invoke the method again, I obtain NULL:
Does anyone know how to make that information always available?
The final goal here is being able to pass data to the client side. I can - for instance -populate an unbounded field with the FieldSelecting event, and would like to ideally read data out of it.
If there are client variables that could be set from the graph, it would work as well.
Thanks!
You likely get null because the script is executed in the top iFrame instead of the main iFrame which contains the control.
The JavaScript global variable px_alls contains the editor controls and can be indexed by editor control ID.
px_alls["edTransferNbr"].getValue();
document.getElementById("ctl00_phF_form_t0_edTransferNbr_text").value;
Script executed in main iFrame context:
When the script is executed in the context of the top iFrame you would have to select the main iFrame.
var mainframe = document.querySelector('[name=main]').contentDocument;
mainFrame.getElementById('ctl00_phF_form_t0_edTransferNbr_text').value;
Script executed in top iFrame context:

Xpages equivalent to Database Script initialize

I am running Xpages in XPiNC.
My usual pattern for an Xpages app is to have a xpHome.xsp page that is set to be the first page that is opened. In this I page I set any scope variables that are at the application level, then head to the "real" first page.
Now I have run into a problem. My current database will send out emails when a status changes, and this will include a doc link to the document, which points to the correct Xpage to open. However, because the user is not going through the home page, then my applicationScope vars are being set.
I thought I could fix this by setting a semaphore in the initApp function - the last thing it would do is to place a "Y" in an applicationScope.semaphore field. So when I open my Xpage the first thing it does is check for that, and if it is null, then I call the initApp function.
For some reason this is not working. But even so I would like to find the equivalent of the old database script "Initialize" event. Something I can call whenever the db is opened for the first time.
How do others handle this problem?
Create a managed Java bean "app" which
works on application scope
sets all application parameters
offers all application parameters
Access the bean with app.xxx in EL or Javascript or call methods directly like app.getXxx() or app.doWhatEverYouWant() in JavaScript.
The bean "app" gets initalized automatically when one of the methods gets called first time.
You can find an example here for start or google for "XPages managed beans" for more Information.
Yes, you have to switch your current code partly to Java but it should be worth it in the long run.
If you want to or have to stay with JavaScript then initialize your application scope variables in a custom control which is included in every XPage like layout.xsp in beforePageLoad event.
Use an additional variable applicationScope.initialized. Check if applicationScope variables aren't initialized yet in JavaScript with
if (!applicationScope.initialized) {
... initialize your applicationScope variables ...
applicationScope.initialized = "yes";
}

Changes to DOM objects are lost after partial update

On a page I have some fields that I want to be "readonly" (in my meaning they can't be accessed but they will store values, read earlier question in this matter if issues...).
I use a client JS setting these attributes on page load:
$(".readonly").attr('readonly', true);
If I have a partial update on any of these fields the attribute is lost and the field is accessible.
What is the best practice to overcome this and make it work?
Every partial refresh has a oncomplete method bound to it. What you could do is add code to the oncomplete method so the item is being set readonly again. Another, better, approach would be not to change the attribute clientside but to have hidden fields which are used to store the data.
When you have an event bound to for instance an Link control you can change the oncomplete code by clicking in your source pane on the event tag. When you browse the events section in the properties pane you will see the onComplete, onError, onStart properties. You can add your own clientside script in these properties.
Before trying to overcome the "problem" You shoud try to understand what exactly partial refresh do and where the state of application is kept.
Unfortunately partial refresh is replacing current html content (or rather part of it) with a newly created one and only form fields that has backing controls will keep state.
I suggest You should try setting readonly property on controls which You would like to make readonly (if there is some logic here You can always use ssjs).
Optionally You can try to preserve the state on the client side by using csjs global variables but this is rather hard to manage.
And one more thing - try to use the technology to solve the problem(xpages) and try not to hack Your way through with use of stuff that You accidentally know (jquery).
I would agree with jjtbsomhorst on using onComplete event. But another alternative could be setting the readonly property via code like this:
var textField:com.ibm.xsp.component.xp.XspInputText = getComponent("inputText1");
var readOnlyAttr:com.ibm.xsp.complex.Attr = new com.ibm.xsp.complex.Attr("readonly", "readonly");
var list:java.util.ArrayList = new java.util.ArrayList();
list.add(readOnlyAttr);
textField.setAttrs(list);
You could call this on the afterPageLoad event of the XPage. But I really don't know whether this would be the best way to about!

XPages Rich Text Component

Is there any chance to get the html content (mime) from a rich text component without any datasource. I would like to grab the content from the field like this. getComponent("FieldName").value but this dosen't work.
thanks.
You can bind the control to a scoped variable; for example, #{viewScope.comments}. You can then retrieve the submitted value from the scope instead of from the component itself; for example, viewScope.get("comments").
Alternatively, you can set a dataContext variable to a JS expression, e.g. <dataContext var="richText" value="#{javascript:return {value:""};}" />. Then you can bind the control to #{richText.value} and retrieve it via the same expression.
And, of course, you could define a managed bean and bind the control to one of its properties. This option provides the most flexibility, but isn't quite as simple as the other two options above.
The solution for my problem is
getComponent("FieldName").getValue()
thanks for your help.

Resources