How to send a document data souce to a custom control in XPages? - xpages

I have this computed text bound to a the body field using EL
<xp:text escape="true" id="computedField1" value="#{doc.Body}"></xp:text>
Now I need to store this computedField in a Custom Control and send in the doc? What property definition should I use, and how do I reference the compositeData to the Body field in the cc
thanks
Thomas

Create a custom property on your Custom Control called dataSource and set the type to com.ibm.xsp.model.DataSource
Create a second custom property called computedFieldName and set it's type to string
In the computed field in the custom control set the value like
value="#{compositeData.dataSource[compositeData.computedFieldName]}"
When using the custom control just set the custom properties like:
computedFieldName="Body"
dataSource="#{doc}"

Related

How do I properly use a Custom Control's "Datasource Picker editor"?

I'm passing a doc datasource into a Custom Control using a property defintion named docDatasource and set to a datatype com.ibm.xsp.model.domino.DominoDocumentData. Just by chance I stumbled upon an editor type named "Datasource Picker". Sounded promising, so I set it to use for m prop definition.
Upon binding the CC into my Xpage - where my doc DS is defined - I indeed can use the picker to choose my datasource ,just as I had expected. But then building the Xpage code I receive an error saying
The value of the property docDatasource cannot be primitive.
So obviously the datatype and the editor don't go along well. There's no harm done really, but I'm curious to learn what else this editor could be used for.
What to do with name of the data source passed to custom control parameter: retrieve its object by simple binding #{requestScope[compositeData.docDatasource]}.
That will return your data source and you can use this binding where needed. Or store it inside local variable and use it instead.
I dont know where you went wrong.
Here is xpage source:
<xp:this.data>
<xp:dominoDocument var="document1" formName="asdf" action="openDocument" documentId="08f6"/>
</xp:this.data>
<xc:doccc dds="#{javascript:document1}"/>
and custom control:
<xp:label id="label1">
<xp:this.value><![CDATA[#{javascript:compositeData.dds.getItemValueString("fl_name");}]]></xp:this.value>
</xp:label>
with custom control property named dds, type com.ibm.xsp.model.domino.DominoDocumentData and editor DataSourcePicker.

xpages, get value of a field in a form from other form

I have two forms Job and Comment,type of these forms are document and response.
There is a field in the Job form that save name of developer and there is a field in the Comment form
that I want to get the name of developer from Job when I want to create a comment for selected job.
One way to get field values from a parent document (in your case from the Job document) is to use a data context to create a parentDoc object. You can then refer to this parentDoc object to get field values from the parent document.
Start by creating a parentDoc data context:
<xp:this.dataContexts>
<xp:dataContext var="parentDoc">
<xp:this.value><![CDATA[#{javascript:
return database.getDocumentByUNID(currentDocument.getParentId());
}]]></xp:this.value>
</xp:dataContext>
</xp:this.dataContexts>
If you just want to display a value from the parent document (and not save it in the response document), you can then use a computed field to display the value from the parent document (using expression language to refer to the field from the parentDoc object):
<xp:text escape="true" id="displayParentField" value="#{parentDoc.field}" />
You can also use the value from the parent document as the default value for an input field:
<xp:inputText id="responseValue" value="#{currentDocument.responseField}" defaultValue="#{parentDoc.field}" />
Short answer, you filter the 2nd data source with the value of the field. It could be the response field on the response doc or the value of the field that exists on both docs.
Long answer, This is a common xPages question, one I have asked myself. Take a look at this question. xPage with multiple datasources has the second datasource always opened in edit mode
A simple solution, I added the below code in default value of Assign field in response form it works now
var parentDoc = database.getDocumentByID(document1.getParentId())
return parentDoc.getItemValueString("Developer")
Thank you Per Henrik Lausten your answer helped me to solve this issue.

xpages passing the UNID to other field

I have an input field:
<xp:inputText value="#{Cdoc.txt_UNID}" id="txt_UNID1"></xp:inputText>
The field txt_UNID is computed having the value: #Text(#DocumentUniqueID).
What I noticed is that even I just compose the xpage containing the document content the inputText already contains some UNID even if the xpage containing the doc content wasn't saved.
There is a button which is showing a dialog containing a field. I want this field to have the value of txt_UNID
Cdoc.save(); // I must save first the Cdoc datasource ?
getComponent('exampleDialog').show()
And the code for the field:
<xp:inputText value="#{Pdoc.txt_CompanieUNID}"
id="txt_CompanieUNID1" defaultValue="#{Cdoc.txt_UNID}">
</xp:inputText>
Thanks for your time.
If your question is whether or not you must first save the document in order to get the UNID, my answer is yes. In my tests, the UNID has changed from a new document to a freshly saved document. So, yes if the current document is new, save before getting the UNID. At least when it was a NotesXspDocument.
I also generally use JavaScript for this,
cdoc.getDocument().getUniversalId();
Otherwise, I am unsure what you are asking.
If PDoc is available at the same level of the hierarchy as CDoc, e.g. both are datasources assigned to the XPage / Custom Control or the same Panel, you could update PDoc on save, using PDoc.replaceItemValue("txt_CompanieUNID",Cdoc.getDocument().getUniversalID()). setValue should also work. Then you would not need the default value.
It just helps keep all business logic in one place. You could also check whether a value has already been set.

How to edit the contents of a RichText field in Xpages using only a basic textarea

How do you disable the CkEditor for Rich Text fields so you only render a basic <texarea> tag with no editor whatsoever?
I'm sure I must be missing something obvious but I don't see to be able to create a document using an XPage with a field stored as RT without using the CkEditor. I want to be able to prompt the user to enter 'a lot' of text but only via a simple multiline input and have that stored as RT.
If I have a..
form with a RT field
an XPage with a xp:inputTextarea control bound to said field
a save button
a documentdatasource linked to that form
on save the document is created with the field value but it's stored as text rather than RT. Adding in computeWithForm to the dds properties doesn't help.
Is the only way to have some kind of querysave or custom converter to manually turn it into RT?
If I use the xp:inputRichText control it saves fine as RT but I don't want the CkEditor in the UI, just a basic . Is there a someway to do a editor=plain to the xp:inputRichText control?
I've been looking at trying to override the dojoType or renderType with no luck
Thanks!
You can use <xp:customConverter> in <xp:inputTextarea> to convert the text to rich text item.
For getAsObject you would write this code (document1 is your data source):
var rtitem:NotesRichTextItem = document1.getDocument().createRichTextItem("rtfield");
rtitem.appendText(value);
return null; // Return null as field has already been created
And for getAsString you would simply fetch the contents of rich text field and textual value.
value.getContentAsText()
The variable value is a standard variable which contains the actual value of the field. So you code for <xp:inputTextarea> would look something like this:
<xp:inputTextarea id="inputTextarea1" value="#{document1.rtfield}">
<xp:this.converter>
<xp:customConverter getAsString="#{javascript:value.getContentAsText()}">
<xp:this.getAsObject><![CDATA[#{javascript:var rtitem:NotesRichTextItem = document1.getDocument().createRichTextItem("rtfield");
rtitem.appendText(value);
return null;}]]></xp:this.getAsObject>
</xp:customConverter>
</xp:this.converter>
</xp:inputTextarea>
NOTE: If you wish to update the rich text field using the text area then you need to write additional code in getAsObject
I am not sure how to manipulate the field type. I assume that Domino know what is going on with the control in much the same way that the custom controls are formatted to match the content type. You might be able to force the content type.
I can present this as an alternative. You can do a custom toolbar in the ckeditor to remove the toolbar and make it appear like a normal text field. There may be UI complications with doing so though. You would also have a status bar to contend with to make it appear as a plain white box. There should be another dojo attribute type for this.
This code will give you a rich text box with no toolbar
<xp:inputRichText id="inputRichText1"
value="#{document1.content}">
<xp:this.dojoAttributes>
<xp:dojoAttribute name="toolbar">
<xp:this.value><![CDATA[#{javascript:var myToolbar = "[['']]";
return myToolbar}]]>
</xp:this.value>
</xp:dojoAttribute>
</xp:this.dojoAttributes>
</xp:inputRichText>

How do you use the Selected property of the navigator?

I've spent days trying to figure this out and I give up.
I am a LotusScript programmer and have been trying to learn XPages. All of the examples and sample programs I've studied only touch on pieces of this.
Can someone explain to me step by step how to use the Selected property of the Extension Library Navigator control?
I have created my own custom control based on the layout control from the Extension Library and created a custom property called navigationPath. I also created a navigator custom control that has 5 Page Link Nodes. In the "Selected" property of each Page Link Node, I put the following SSJS:
if(compositeData.navigationPath == "/Home/ApplicationPool"){
return true
}else{
return false
}
/Home/ApplicationPool corresponds to the value I put in the "Selection" property of the particular Page Link Node.
In each layout custom control, I set the "navigationPath" property to compositeData.navigationPath.
What did I miss?
there is a selected and selection property and they mean very different things and can't be used at the same time. In the code example in your question above you are using the selected property which is the wrong one in this case.
Your treeNodes in the navigator should be setup to use the selection property, this is a RegEx value that is used to see if it matches the value passed into the application layout via the custom property.
<xe:navigator id="navigator1" expandable="true" expandEffect="wipe">
<xe:this.treeNodes>
<xe:pageTreeNode label="nodeName" page="/page.xsp" selection="/Home/ApplicationPool" />
</xe:this.treeNodes>
</xe:navigator>
As you can see you don't need to use any SSJS to evaluate a true/false outcome. Just match the value in the treeNode to the one in the XPage's applicationLayout control.
If your using tabs in the layout titleBar then you can set a selection property there also that uses the format /Home/.* which will make that tab highlighted for every XPage that have /Home/ at the start of it's navigationpath custom property. Don;t forget it is RegEx so any valid RegEx statement can be used here adding more power to this particular property.
For the tree nodes in the navigator control you define the name of the xpage to open and then the related selection. Example:
<xe:pageTreeNode page="/text.xsp" selection="/Home/Test" label="Test page">
</xe:pageTreeNode>
For the individual xpages using the applicationLayout you define a value for navigationPath. If this value matches an entry in one of the tree nodes the naviagor control, then the corresponding menu item will be highlighted in the browser. The best way to define the value of the navigationPath is by using a custom property (as you are using). Here's an example of that:
<xe:applicationLayout id="applicationLayout1">
<xe:this.configuration>
<xe:oneuiApplication navigationPath="${javascript:compositeData.navigationPath}" ...
You can see examples of using all this in the Extension Library Teamroom and Discussion templates.
Based on my explanation on how to use it, I can see that you are not using the selection property on the navigation control correct. You just need to define a unique value for each tree node (which then will be used if it matches navigationPath on the individual xpages).
So for your specific example change your selection property to just return: "/Home/ApplicationPool"

Resources