java.util.ArrayList incompatible with [Ljava.lang.Object check box group - xpages

I have a Check box group, whose values are computed by using the selected values of another Check box group. So when I do
var check6:com.ibm.xsp.component.xp.XspSelectManyCheckbox = getComponent("check6");
ArrSelected = check6.getSelectedValues();
to get the selected values, the following exception occurs:
Error calling method 'getSelectedValues()' on java class 'com.ibm.xsp.component.xp.XspSelectManyCheckbox'
java.util.ArrayList incompatible with [Ljava.lang.Object;
Check6 gets its values from a session scope variable that is computed on beforePageLoad event and I have also set the default value.
Note that this does not happen onload of the page, but when the first partial refresh happens. Does anyone know what this exception indicates?
Thanks a lot!

Bind the value of the selectItems for the second check box group to precisely the same expression the first checkbox group's value attribute is bound to.
This article provides a lengthy description of the reason why, but here's a very quick summary: if you ask a component what its value is, it has to ask the data it's bound to. So skip the component, and ask the data yourself.
So, if your first group looks like this:
<xp:checkBoxGroup value="#{currentDocument.FirstField}">...
Then your second group should look like this:
<xp:checkBoxGroup value="#{currentDocument.SecondField}">
<xp:selectItems value="#{currentDocument.FirstField}">
</xp:checkBoxGroup>
When the user's selection in the first group is posted to the data source, the second group will reflect the changes because they're linked to the same property on that data source. Slight caveat: if your page includes any required fields, you may need to skip validation on the onchange event that triggers the second group to recalculate.

the reason is simple, this class has no method getSelectedValues() (as far as I can see it, look here for more info: http://public.dhe.ibm.com/software/dw/lotus/Domino-Designer/JavaDocs/XPagesExtAPI/8.5.2/index.html?overview-summary.html)
Maybe you could bind the control to a scoped variable and then access this variable to compute your other values?

Related

Xpages - Custom control getting a custom property from another custom control

I've searched google and stack but can't seem to find a definitive answer. What I would like to do, is something like this:
Say I have custom control A, within which, is a radio button, when I click it, I want it to grab a custom property that is set on custom control B, lets say compositeData.Name as an example. Can I do this?
If I give custom control B an ID, lets say ccB, can the radio button in custom control A do something like, getComponent("ccB").getValue().compositeData.Name so I can get the value of the property I passed into custom control B using the custom property 'Name'?
If its a straight no, at least I know to stop playing around with the idea! Thanks
Reaching from one control into the inside of another control would break component isolation. You might want to take a different approach:
Option a - client side:
Your control emits a JavaScript event that bubbles up until it reaches a parent element that contains the control you want to change (presumably the parent Dom element). There you set the property of that element.
Option b - server side:
As Urs suggested: bind both to a bean and handle the updates inside the bean

How to find programmatically (SSJS) what item of the underlying doc the UI input control on Xpage is bound to?

The task is that I need to update the field of the underlying doc only given the id of the edit box or the combo box on the Xpage. All that has to happen before the page is actually saved. Cannot find any methods in UIComponent and subclasses that allow to find out the name of the actual doc item the current XSP input control is bound to. Plz help.
The following will get the Expression Language binding for a component with the id inputText1:
var inputText1:com.ibm.xsp.component.xp.XspInputText = getComponent("inputText1");
var valBinding:com.sun.faces.el.ValueBindingImpl = inputText1.getValueBinding("value");
return valBinding.getExpressionString();
This will return e.g. "#{document1.myField}". Using basic string parsing, you should be able to get what you want.
Like Oliver, I'd be interested to hear the use case. It's not something I've had the need to use.
As a bonus, try looking in the Local folder in Package Explorer at an XPage / Custom Control. You'll see all the getters / setters for components on your XPage, which will give you hints for what properties and methods are available. F3 and F4 are very useful for seeing all methods/properties and class hierarchy.

How do I access a repeat control from the outside e.g. via CSJS

How can/should I access a repeat control from outside? In my case I want to calculate some additional value(s) for the items in the repeat control and update each item with jquery.
In SSJS you always access a component with getComponent("id"). If your contents of the repeat are just a view than define the view data source at the XPage level, not the repeat and you can use the id of the datasource to get the view object, ie, view1.
From SSJS you can access the repeat control itself via getComponent(). However, if you want to access components within the repeat, it gets more challenging.
The default behaviour is to create a single "row" of components for the repeat and then, in the Render Response phase, iterate over them to generate the relevant HTML for the appropriate number of rows (rows property of the repeat control) from the relevant start point (first property of the repeat control, which may have been incremented by a pager), picking the data from the relevant data (value property of the repeat).
If the repeat has repeatControls="true" set, at page load the runtime creates a set of controls for the appropriate number of rows (rows property of the repeat control). However, accessing them may still be a challenge. This will also remove the ability to use a pager.
If you want to manipulate e.g. the appropriate view entries within the repeat, one option might be to load into viewScope the UNID / Note ID via a computed property within each row. E.g.
rendered="#{javascript:if (view.isRenderingPhase()) {
if (idex == 1) viewScope.put("myVar", new java.util.ArrayList());
viewScope.get("myVar").add(entry.getNoteID());
return true;
} else {
return true;
}"
This initialises (or re-initialises) the viewScope variable if it's the first row (please double-check first row has idex as 1, idex being the variable name you define for the indexVar property of the repeat control), and adds the NoteID to the list. So element 0 is the NoteID of the first row, element 1 the Note ID of the second row etc.
If you wish to manipulate values, you may be able to take a similar approach by using dynamic binding. There are various questions on StackOverflow about dynamic binding for repeat controls as well as blog posts, probably by either Tim Tripcony or Jesse Gallagher.
Beyond this, CSJS may be the easiest way to manipulate the contents of the repeat. Just be aware that if you do a partial refresh whose refreshId is the repeat, it may replace whatever you've done client-side.

"Visible" property on XPages edit boxes based on checkbox selection(s)

I am new to XPages, and I have a Check Box Group ('checkBoxGroup1') as one of my design elements that contains three choices ("CBChoice1", "CBChoice1", "CBChoice1"). Underneath that Check Box Group, I have three edit box fields which correspond to the three checkbox choices. Each time one of the checkbox choices is chosen, I want the corresponding edit box to become visible.
Whenever one of the checkboxes is chosen, I have it partially refreshing the panel that the edit boxes are in, but I cannot figure out the code in each of the edit box's visible property. I started with
getComponent('checkBoxGroup1').getValue() == "CBChoice1"
which kind of works, but isn't the answer. I also tried
var valueArray = getComponent('checkBoxGroup1').getSelectedValues();
valueArray[0] == "CBChoice1";
which seems more on target, but I was getting the following browser error:
Error 500 HTTP Web Server: Command Not Handled Exception
I notice that in the computed code for the visibility property, it is SSJS. I feel like I am close, but have been banging my head for too long. Any help would be greatly appreciated.
A better method might be to bind the checkbox group to either a document data source or a scope variable.
Then, your visible property might look something like:
#Contains(myDoc.getItemValueArray("checkBoxFieldName"),"CBChoice1");
or
#Contains(viewScope.get("checkBoxScopeVar"),"CBChoice1");

Getting value of label based on composite data

I have a custom control that has a property I have defined. I use the composite data a label which is on the custom control. The label displays just fine but I wanted to use the value of the label on a control that is outside the control with the label and composite data.
But it is returning null for the value of the label. It seems like that composite data is being calculated every time the label value is accessed and the reference point for the calculation seems to be the control accessing the label value rather than the control where it is contained.
I plan to use scope variables instead but is there any way I can make composite data work?
Composite data only exists inside the custom control that defines it. As such, it is far easier to reach outward than to reach inward.
In addition to scope variables, an alternative is to define a dataContext. This is technically still a use of scope variables, as it pushes a variable temporarily into the requestScope, but is slightly easier to work with because you don't have to explicitly tell it to do so... it just does it. For example:
<xp:view
xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.dataContexts>
<xp:dataContext
var="labelValue"
value="#{someExpression}" />
</xp:this.dataContexts>
<xp:text
value="#{labelValue}" />
<xc:labelContainer
labelValue="#{labelValue}" />
</xp:view>
In the above example, everywhere within the container to which I've attached this labelValue dataContext, I can just refer to #{labelValue}, and it will return whatever value the expression for that dataContext returned. This provides you, then, a single variable that can be used within the XPage itself, but also passed into custom controls.
I like Tim's suggestion with the data context. However if you have to, you could access the value on the propertyMap of the control. This wouldn't be the label but the composite data. This is how components could 'talk back'

Resources