Dynamically add custom control on Xpage - xpages

how can I add custom control on the basis of sessionScope variable. I try include page container control but no luck:
<xp:this.afterPageLoad><![CDATA[#{javascript:sessionScope.put("viewName","ccViewAll.xsp");}]]></xp:this.afterPageLoad>
<xp:text escape="true" id="computedField1">
<xp:this.value><![CDATA[#{javascript:sessionScope.get("viewName")}]]></xp:this.value>
</xp:text>
<xc:appLayout>
<xp:this.facets>
<xp:panel xp:key="facetMiddle">
<xp:include id="include1">
<xp:this.pageName><![CDATA[${javascript:sessionScope.get("viewName")}]]>
</xp:this.pageName>
</xp:include>
</xp:panel>
</xp:this.facets>
</xc:appLayout>
The above code give me error Error 404 HTTP Web Server: Item Not Found Exception. But when I hardcode the viewname that is ccViewAll.xsp instead of sessionScope.get("viewName"), its work fine.
-MAK

You can use the dynamic content control or the switchFacet control if you have the ExtLib for XPages. The Teamroom template (demo application that comes with the ExtLib) uses these in the "allDocuments" Xpage or the "allDocsAllTab" custom control, these are good examples to look at.
If you don't have the ExtLib you could use the loaded / rendered property of a custom control to decide which one gets loaded.
e.g.
<xp:panel key="MiddleColumn">
<xc:customControl1 loaded="${javascript: if(viewScope.control == "customControl1")}"></xc:customControl1>
<xc:customControl2 loaded="${javascript: if(viewScope.control == "customControl2")}"></xc:customControl2>
</xp:panel>
loaded = false means that nothing will be done for this control.
rendered = false means that the control will be created but hidden, you can change this later to show it.
use rendered if its going to change for example when a button is clicked and loaded when its decided at start up and won't change while the user is logged in.

If you are using this to show a different view in the domino database based on some other selection that I would suggest looking at the Extension Libraries 'Dynamic View Panel' control.
Using this control means you won't need to create different custom controls for each view that you want to use, just a single page with this control and point it to the correct view to display via a scope variable.
If you need to customize how each view displays you can create a viewControl bean to set additional properties based on the view that it is showing.

Something worth to mention is that if you don't use the ExtLib - If you're using Partial Refresh then you HAVE to use the rendered property, since the loaded property only can be calculated on pageLoad.
From my understanding this means that every custom control will be computed by the server and that's probably not something you want. (Added overhead, for one thing.)
/J

Related

Show custom controls on webpage in other order than layed out in DDE - Xpages

I have a number of custom controls layed out on an xpage. I want these controls to be displayed in the order of a setting in a notes document
So my xpage might look like this in DDE
CustomControl1
CustomControl2
CustomControl3
CustomControl4
but when the custom control is displyed on the webpage the custom controls should be displayed in the following order (based on the setting document)
CustomControl4
CustomControl1
CustomControl2
CustomControl3
anyone have any ideas how to accomplish this (server side)
You can use the xp:switchFacet in combination with a xp:repeat to calculate the order at runtime like this:
<xp:repeat
id="repeat1"
rows="30"
var="rowEntry">
<xp:this.value><![CDATA[#{javascript:var arr = ["Control1","Control3","Control2"];return arr;}]]></xp:this.value>
<xe:switchFacet
id="switchFacet1"
selectedFacet="#{javascript:rowEntry}">
<xp:this.facets>
<xp:panel xp:key="Control1">Control1</xp:panel>
<xp:panel xp:key="Control2">Control2</xp:panel>
<xp:panel xp:key="Control3">Control3</xp:panel>
</xp:this.facets>
</xe:switchFacet>
</xp:repeat>
Instead of the Array arr you can use data based on a document or xsp.propertie. The Output of this code is Control1 Control3 Control2 and in your Designer you have your controls inside switchFacet in following order: Control1 Control2 Control3.
Without knowing the real pain of your project I can only assume that the individual position needs to be defined at runtime, or something like that.
In general: controlling a page's layout is a pure CSS job. On the resulting page almost anything can be positioned almost anywhere within the page's range, and it doesn't matter where it was placed at design time. So, if you enclose your custom controls within their own containers (panels / divs) then you should be all set. You might define positioning classes in CSS and then have some SSJS code decide which class is assigned to what div.
If for example you have a custom control for each day of the week, and you always want to have the current day at the top-most position, then you could define 7 css classes as in ".today", ".todayPlus1", ".todayPlus2" ... ".todayPlus6". Write your positioning rules for each class. And finally compute each panel's styleClass property based on the current week day.

xpages extension Library dialog read only

Can the xpages extension library dialog box (xe:dialog) be open so that it's fields are read only ?
Lotus Domino 8.5.3 version update 1 extlib
Thanks
If you make a panel control read only, the controls within the panel control are read only too. So, add your fields inside a panel control and make it read only:
<xp:panel readonly="true">
Add your fields here
</xp:panel>
The content of the dialog is defined by the structures declared within it, so you'd just make your elements within the content area computed text, or readonly fields, however you want to do it. If your question is can it be opened read-only sometimes, save a variable to the scope and use that to determine whether or not to render controls as editable.

How to pass var variable to custom control

I want to create a generic action bar custom control with Save, Edit, Delete, ... buttons.
How can I pass var variable from xpage to a custom control?
Update
I successfully transferred document object to custom control and I can Save the changes made in document, but I can't delete it with same object.
Update:
<xp:this.action>
<xp:executeScript
   script="#{javascript:compositeData.datasrc.save()}">
</xp:executeScript>
</xp:this.action>
Delete is not working:
<xp:deleteDocument
message="Do you want to delete?"
var="#{javascript:compositeData.datasrc}">
<xp:this.name><![CDATA[#{javascript:var page = sessionScope.get("prevview");
return (page=='')?'home.xsp':page}]]> </xp:this.name>
</xp:deleteDocument>
I tried also with:
var="#{javascript:compositeData.datasrc.getDocument()}">
but also didn't work.
When you define a custom control, you can specify control properties. These properties then show up in the property editor when you insert the custom control into an XPage or another control. You can specify the data type and allow them to repeat.
This is saver than to rely on scoped variables. Check Chris' introduction and the XPages 101 session or and many more for inspiration
You can do it for example with a Scoped Variable. If the variable value is specific to that XPage (and user) viewScope is probably the best.
The above options are the best way to do that, but keep in mind that if you define a variable in a scriptblock or somewhere else in the Xpage, you will be able to access this variable from your code in the CustomControl, too. I think that's because the XPage und the custom Controls are kind of merged when compiled. Keep that in mind, this can lead to very nasty problems, especially with recycling issues.
What is the purpose of this variable ? If its a variable to control which buttons are being shown it would be best to create properties for each button / section. These properties can be computed to either return true or false.
If you want to pass the code that a button should execute I would advice you to generate button bars for the most common locations ( aka actions ) and add custom buttons on the button bar by using a facet (Editable area its called in the designer) .On this facet you'll drag a panel on which the buttons are being placed.

learning how to use xe:dominoViewEntriesTreeNode

I realized my question was too vague on adding navigation items dynamically, so I am rewriting the question.
I have discovered the xe:dominoViewEntriesTreeNode control from the xpages. I think I can use this to add navigation items to the navigator control based on entries in the view.
I am struggling to find very much in the way of documentation or resources that break down how to do that. Can anybody to me to a good reference or example code?
You can use dominoViewListTreeNode to build a menu based on views in a database (and not documents in those views).
Here is an example of using xe:dominoViewListTreeNode to dynamically build a menu based on all views called "Test*" (using regex in the filter property). When selecting a menu item from the menu, the name of the view is submitted to the server (using EL notation for the viewEntry.getName() method).
The example also contains an onItemClick event handler that "catches" the name of the view as the submitted value and stores this in a sessionScope variable. The event handler then redirects to a views.xsp XPage that could contain a Dynamic View Panel control where you could use the sessionScope variable to control what view to show.
The sessionScope variable is also used to mark the selected menu item as "selected".
<xe:navigator id="navigator1">
<xe:this.treeNodes>
<xe:dominoViewListTreeNode filter="Test.*" submitValue="#{viewEntry.name}" var="viewEntry">
<xe:this.selected><![CDATA[#{javascript:viewEntry.getName() == sessionScope.clickedView}]]></xe:this.selected>
</xe:dominoViewListTreeNode>
</xe:this.treeNodes>
<xp:eventHandler event="onItemClick" submit="true" refreshMode="complete">
<xp:this.action>
<![CDATA[#{javascript:sessionScope.clickedView = context.getSubmittedValue();
context.redirectToPage("views.xsp");}]]>
</xp:this.action>
</xp:eventHandler>
</xe:navigator>
Instead of the onItemClick method to redirect to an XPage, you could compute the href property of xe:dominoViewListTreeNode to return the name of an XPage.
I have a short presentation called "XPages Extension Library - Create an app in 1 hour (almost)" that presents this technique (and other techniques).
I assume you have an area on your page carrying the navigation items, e.g. links to some pages with link texts?
I would then use a repeat control with a datasource/javascript source that returns the document item values from your profile document or something.
If you are not into repeat controls then you should consider to read this: http://xpageswiki.com/web/youatnotes/wiki-xpages.nsf/dx/Work_with_repeat_controls
On this page there is also a sample dealing with a profile document.
By the way: using profile documents was always a crutch, so consider to youse "normal" config documents instead.

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