What is the "binding" property of controls and how do you use it? - xpages

The "binding" basic property is described as a property that "Specifies an expression that binds a control to a particular control property". I tried to google and read at HCL docs but there is no example on how to use it.

The binding property allows you to specify an object property (say, on a managed bean or dataContext) that will be set to the specified component. For example, you could do:
<xp:inputText binding="#{someBean.textField}"/>
...and that would call someBean.setTextField(XspInputText inputText).
All that said, it's kind of an edge-case property. I've made good use of it, but it's largely an artifact of earlier JSF revisions, when it was more common to have backing logic that "knew" about the front-end XPage explicitly.
In general, it's better design to stick to value bindings like value="#{someBean.firstName}" and not make your backing objects aware of the front-end UI, unless you have an explicit reason to do otherwise.

Related

User roles and workflow status xpages and managed bean

To not have to keep repeating some validations, for example, who can see a button in a certain status of a document in the worlflow, I'm using session, scope, and session variables to store the user roles and application variable to store the Status related to each area.
I was evaluating whether it would be better from a performance and build point of view to implement a managed bean, to return the user roles and the possible statuses of each participating workflow area. Would it be the best structure in fact? What do you think? I do not have much experience in java. How could I construct the structure in java, several methods, one for roles and the other for set of status associated with the area that would name the related method? You could return the results of this method in arrays, or there is a better return structure.
Thanks a lot!
My best suggestion is to adopt the pageController Methodology. Then it's more like true MVC. This has been talked about on NotesIn9 screencast many times but basically you have a java object that's bound to your XPage. In effect it's a viewScoped bean that holds all your page logic. Then you can have methods like isGroupMember(), hasRole() etc and calculate that on the pageInit. There's little need to hold onto that in sessionScope in my opinion. So for example I have this in my pageController :
public boolean isGroupMember(String groupName) {
return JSFUtil.getXSPContext().getUser().getGroups().contains(groupName);
}
So that's available to each page. BUT I don't need to copy that snippet onto every page controller. In Java you can have your page controllers extend a more generic class. so I have a "base.pageController" class. All the specific page controllers extend that. So this isGroupMember() code goes into the base and then it's available to be used on every XPage. Doing it this way gives you the ability to have generic functions like this and then hold more specific function that are only for the individual page.
You can also have a hasRole() function etc...
Recommend you check out this video : http://www.notesin9.com/2016/08/25/notesin9-196-no-dependency-page-controllers/
Also for a question like this, I recommend you just use the xpages tag. Adding others like javabeans can bring people in who know nothing about XPages and XPages is unique enough of a beast that outsiders can cause some confusion on occasion.

Storing properties of a custom component in session scope or bean

I've written a new back-end Java component (extending UIComponentBase) as an alternative for the ExtLib Application Layout control. The control needs to show a collection of data that is looked up from another Notes application. The data is user dependant and doesn't change from page to page so, to avoid repeatedly doing a lookup to the other application, I want to store it in the session scope. (Note that because this is a layout control, there will only ever be one per page.)
I know I could use a session-scoped maanged bean (and have done in previous iterations) but the data only needs to be used in this control and shouldn't be used elsewhere on the page which it could be with a bean. So my question is, what's the best practice approach I should take here? Should I just directly store the data in the sessionMap or am I missing a trick with the component stateHolder? Or am I stuck with using a bean?
Thanks
(Edited for clarification)
It looks like you're talking about your own back-end Java components rather than Custom Controls within a single NSF.
I'm not sure at what level, when you write your own native XPages components, the properties are cached by the stateHolder when calling saveState(). I would presume no higher than View, for the reasons Frantisek says, that otherwise it would be unclear which instance to update if you had multiple on one XPage but one on another. It couldn't update both at the same time on the same page, so I would guess that each is a separate instance. As a result, the same component on multiple pages would be a separate discreet instance.
But there's nothing stopping you, in specific setters of the component, writing to sessionScope as well as the private property, and then doing the reverse on the getter. I'm not sure if you'd want to try the internal property before trying sessionScope or vice versa. It would depend how you wanted to handle the situation of the same sessionScope being updated from multiple pages (if the collection could change).

how can I access endpoint properties set in faces-config.xml programmatically?

I am using the IBM Social Business Toolkit. I have defined a connection for my Notes app via endpoints in the faces-config xml file. I wonder how I can access this file pro grammatically since I could not find a service that returns me the base url of IBM Connections.
It's useful to remember that an endpoint definition is really just creating a managed bean. The managed bean has a variable name you refer to it - the managed-bean-name property. You can access this directly from SSJS or via ExtLibUtil.resolveVariable() in Java. The definition also tells you the Java class that's being used, e.g. com.ibm.sbt.services.endpoints.ConnectionsBasicEndpoint. That really gives you all the information you need to get or set the properties.
So from SSJS you can just cast it to the class name, e.g.
var myService:com.ibm.sbt.services.endpoints.ConnectionsBasicEndpoint = connections
So the bit after the colon will be the managed-bean-class value and the bit after the equals sign will be the managed-bean-name. In Java, you can use
ConnectionsBasicEndpoint myService = (ConnectionsBasicEndpoint) ExtLibUtil.resolveVariable(ExtLibUtil.getXspContext().getFacesContext(), "connections");
You'll then have access to all the methods of the class, so you should be able to retrieve what you need.
The properties are part of the Java class, who are referred to in the Faces-Config.xml. So get the class by his fully qualified name or by bean name and set or get the properties
I think the best route will most likely be what Paul is suggesting: resolve the variable by its name and use the getters to get the effective properties that way.
Sven's suggestion is a good one to keep in mind for other situations. By accessing the faces-config.xml file as a resource, you could load it into an XML parser and find the values using XPath. I'm doing much that sort of technique in the next version of the OpenNTF Domino API, which will have a set of methods for manipulating the Faces config. However, one key aspect there is that reading the XML file directly will just get you the string values, which may be EL expressions, whereas going the resolveVariable route will get you the real current properties.

How to import two cc both contain compositeData?

I do not know that the question is right? Please do not take it your mind if it is crazy. Actually I am working on xpages application. There I need to do two things, that I want to add the picklist functionality and binding the dynamic data like field_1,field_2,field_3, ... upto n depands on customer choice.I am using the composite data for both custom controls. I can remove the picklist control's composite data and also I can do it by passing the scope variables. But that takes more time than the composite data.
I did not get any error. But the binded documents is not saving.
Is it possible to import the CCs that are having composite Data?
Code for first CC:-
<xc:viewpicklist datasrc="view1" dialogID="dialog1" dialogWidth="700px" dialogTitle="Pick this field value!!!">
<xc:this.viewColumn>
<xp:value>0</xp:value>
<xp:value>1</xp:value>
<xp:value>2</xp:value>
</xc:this.viewColumn>
</xc:viewpicklist>
Code for Second CC:-
<xc:BOM_Partinfo BOM_Partinfo="#{document1}"
TNUM="field#{index+1}" Desc="Desc#{index+1}" quan="Ea#{index+1}"
exp="exp#{index+1}" cap="cap#{index+1}" total="price#{index+1}"
RD="RD#{index+1}" m="manufact#{index+1}"
m_n="manufactnum#{index+1}">
</xc:BOM_Partinfo>
You can read information that is set in the properties of a custom control if it was static in the calling page:
var x = getComponent("yourcomponentid");
x.getPropertyMap().get("parametername");
but you want to propagate a data source from the outer control to the inner control...
You need to plan carefully. If you hand over the data source, then your custom control is dependent on a fixed set of fields in the data source (that would be a parameter of type com.ibm.xsp.model.DocumentDataSource). This would violate the encapsulation principles. So I would recommend you actually hand over data bindings - the advantage: you are very flexible what to bind to (not only data sources, but also beans and scope variables would work then). The trick is you provide the binding name as you would statically type it in (e.g. "document1.subject" or "requestScope.bla" ). In your control you then do
${"#{compositeData.field1}"}
${"#{compositeData.field2}"}
You need one for each field.
You cannot send a document data source to a custom control using composite data parameters.
You can try and use this script instead
http://openntf.org/XSnippets.nsf/snippet.xsp?id=access-datasources-of-custom-controls
Define data source in XP/CC where you want those CCs. Define parameter "dataSourceName" for both CCs. Inside each of them use EL "requestScope[compositeData.dataSourceName].fieldName" everywhere you want to bind to datasource.

Custom Control Custom Methods?

I have been making good use of custom properties withing custom controls. Is there such thing as custom methods? Say I want something to happen in a CC. A good example is the show method of the dialog box extension. If I have a cc with a extension dialog inside, I want my custom control to have a Show method which insulates the end user programmer from the extension pages Shoe method.
Is there anyway to do this?
At runtime, all Custom Control elements become instances of the UIIncludeComposite class; as such, there are many built in methods that you can call against any given control instance, but there is no way to specify custom methods, as opposed to custom properties.
There are, however, at least two ways you could achieve the result you're after:
Convert your Custom Control to a component (this NotesIn9 episode describes the simplest approach to this process). Once you've migrated the class that Designer generated to one that won't get overridden every time you build your NSF, you can add custom methods without fear that the next build will just wipe them out again. Since Custom Controls are essentially just IBM's implementation of the JSF 2.0 notion of "composite components", you could also create a component from scratch that has the same behavior as your existing Custom Control but also supports custom behavior. Note that either approach does not necessarily require that you create an OSGi library... you can define these components directly in an NSF; you only need to push them to a library if you want to reuse them across multiple NSFs without having to copy the various files to each.
In the custom properties for your control, include one property that accepts an API object. In other words, you could create any object (say, a Java class or SSJS object) that supports the custom methods you wish to define, and pass that object to the control. You could then call those methods by getting a handle on the object via the CC's property map.
For example:
<myCC id="myCustomControl" API="#{someObject}" />
Assuming whatever #{someObject} resolves to includes a show() method, you can call that method by getting a handle on the instance that has been passed to the control:
var cc = getComponent("myCustomControl");
var ccProperties = cc.getPropertyMap();
var ccAPI = ccProperties.get("API");
ccAPI.show(cc);
In the above example, I'm passing the actual Custom Control to the show() method, because the object itself isn't aware of the Custom Control it was passed to. So if that method needs to get a handle on its children to toggle their rendered property, for example, then it needs some other way of determining its context.
Tim's solution with passing in the object is a great solution to that.
Just something that popped into my head, would be easy to make a property similar to the rendered property on a control. Pass in a value and inside the custom control do something based on its value ie. if true display dialog, else hide, in the XPage during run time modify this value and partial refresh the control, the logic will be re run by this and the control will display etc.
Another solution could be to include a JavaScript library in your custom control providing functions (your custom control methods) where you'd have to pass in the id of the custom control instance.

Resources