xe:breadCrumb Use Without Tree Nodes? - xpages

I have an XPages app with a page > sub-page structure that is defined by URL parameters prior to our company's adoption of Domino 8.5.3 UP1. Now that we do have UP1, I've been eyeing up the xe:breadCrumbs control with a little bit of envy. Not being familiar with xe:pageTreeNodes (which I know at least exist thanks to my copy of XPages Extension Library), I figured I'd "phone a friend". I couldn't find much on the topic. My question is two-fold:
How should one implement page tree structure to use properly with the xe:breadCrumbs control?
With my current setup (root page being standard page parameter, sub-page being a second, custom parameter), how easily can I use my setup with xe:breadCrumbs?
At some point, I'm more than willing to cut my losses and just build out a quasi-breadcrumbs element with some computed xp:link controls in a div. Since the opportunity arose, I figured I would check and see if there were some better options. I know this is a little vague, but I think the idea is communicated here.
[Edit:]
I should probably ask if this is something more directly and exclusively used with the xe:navigator. If that's the case, then I may be a little more sad, but a bit less confused.
[/Edit]

Tree nodes are fine. Here is small example. Prerequisites:
all documents are in the same database. Not a big issue, just update href params accordingly.
Document contains fields with ID and Label (subject, title) of parent documents (all levels)
There is view "id" containing only one column sorted by document's id to open it (Domino syntax) - see also: native Domino links and XPages
dds is curent document's datasource
ddsParent is parent document's datasource
<xe:breadCrumbs id="breadCrumbs1">
<xe:this.treeNodes>
<xe:basicLeafNode label="Top document: ${dds.fld_TopLabel}">
href="/id/${dds.fld_TopID}">
</xe:basicLeafNode>
<xe:basicLeafNode label="Sub1: ${ddsParent.fld_Label}">
<xe:this.href><![CDATA[#{javascript:"/0/" + ddsPonuka.getDocument().getUniversalID()}]]></xe:this.href>
</xe:basicLeafNode>
<xe:basicLeafNode label="Current level: ${dds.fld_Label}">
</xe:basicLeafNode>
</xe:this.treeNodes>
You have to alter this for every XPage. Sure, you can make it a custom control with parameters, but you will end up with custom control on every XPage fed by parameters roughly in the same structure.
The best option is to make managed bean configurable in some sort and returning ExtLib tree objects. Then your source will be reduced to:
<xe:beanTreeNode nodeBean="my.bean.Class"></xe:beanTreeNode>
Best example is XPagesExt.nsf bundled with ExtLib distributions.

Related

Xpage, createForm=false disables SSJS events on links?

I ask this just to be clear here: I accidently set the createForm property to false. I then expected a link event that should open another page only not to function any more.
Is this the intended behavior of SSJS events e.g. in links when you disable form creation?
As Per mentions, all events require a form: if they are full refresh, then the page needs a form to post to in order to trigger the redirect; if they are partial refresh, the form determines the contents of the AJAX POST.
The XPages runtime includes support for a form component, but it is not included in the component palette (and it cannot be added via Designer Preferences), so the only way to add it to a page is by editing the source XML directly. For example:
<xp:form>
<xp:link id="exampleLink" text="Example Text">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:// event code}]]></xp:this.action>
</xp:eventHandler>
</xp:link>
</xp:form>
There are (at least) two reasons why this component is useful:
It can improve performance. If a page contains different areas that are functionally distinct -- in other words, an event in one portion of the page does not need to be aware of data in any other portions of the page -- then wrapping each section in a separate form component causes each event to only post data that is contained inside the same form as the component that triggers the event. Your question indicates that the link that broke when you set createForm to false should navigate the user to another page; it's likely, therefore, that this event doesn't need to know about any field values, because the user is leaving the current page anyway. If that's true, wrap this link in its own form, and any fields inside a separate form, and the link will perform marginally faster because the browser doesn't have to post any field data... just the identifier for the link itself.
It can provide style flexibility. It's common for a developer to receive, separately from the actual end user requirements, pre-determined CSS from a designer unfamiliar with Domino -- for instance, if the site design is outsourced, or must adhere to corporate style guidelines. This often becomes a source of tension when the designer has made certain assumptions that, at first glance, are incompatible with the markup that Domino generates. One of the most common examples of this is when the site contains search features, because most web developers will have one form for search and a separate sibling form for any other fields. This can increase the cost of a project when either the designer or the developer has to revise a stylesheet that the designer already developed to account for a single form tag surrounding all the content. In short, suppressing the default form element and explicitly specifying form components where needed makes it easier to adhere to externally imposed style guidelines.
So there are many use cases where it's actually preferable to use one or more form components on an XPage... just remember that all data and events must be inside a form -- whether the default form that usually surrounds all the content, or a manually included form component -- and that forms cannot be nested. You can add as many form components as you want, but they must be siblings. No form can contain another form.
Yes, because you are doing HTTP POST requests and they require a form.
You can convert your POST request link to a GET request link instead be removing the SSJS event and creating a "basic" link instead:
<xp:link escape="true" text="Link" id="link2" value="/somepage.xsp"></xp:link>
But if you need the SSJS logic, then you also need to have a form.

Can you compute which custom control to use?

Think "computed subform", but in Xpages.
On one of my custom controls, depending on a certain value, I want to either present a custom control that renders a drop-down list using a combobox or renders an input box with a type-ahead.
This is on a custom control that renders a view, with all view configuration choices handled by a document rather than design, so several different views utilize the same custom control.
For example: I have a By Status view using the custom control that has status as the first column and we use a combobox to allow the user to select which Status value to filter by. Another view is sorted by Requisition number and I want to use a type-ahead instead of the combobox.
My preference is to use the same dynamic view custom control for both and have a formula that determines which of the two (comboBox or inputText) to use. How do I compute which custom control to load?
(Credit for the dynamic view control goes to Scott Good's folks over at Teamworks Solutions.)
During it's life cycle, an XPage exists in two places. First of all a representation of the XPage's relevant components is stored on the server. Then the page goes through a lifecycle, retrieving properties from documents, checking which components should be rendered, retrieving the data for any repeating control such as a View Panel etc., and passing the relevant HTML to the browser. The browser is the second place it exists.
So you can't compute a custom control as such. All you can do is set the loaded property, and loaded needs to be based on a non-dynamic calculation such as a viewScope variable, the current XPage name, a view name stored on the XPage etc. What you would have difficulty doing would be using a different custom control based on data on that row entry.
The other option is the Dynamic Content control or Switch control from the Extension Library. Both are similar to using the loaded property, in that you're putting both custom controls on the page and choosing which to display.
From what you're describing, the loaded property should cover what you need.
Some time back I saw this question on StackOverflow where the author had used Include Page control (xp:include) to include custom controls using pageName attribute based on formula.
<xp:include>
<xp:this.pageName><![CDATA[${javascript:sessionScope.ccPageName + ".xsp";}]]> </xp:this.pageName>
</xp:include>
Similar to the technique described by Paul Withers in his answer the attribute of pageName is also computed on page load.

Reusable edit form in Apache Wicket

I have a simple ContactEditPanel which contains a form and a number of textfields. Up until now I included an AjaxSubmitLink in this panel which, if the form content is valid, saves/updates the Contact instance contained in the Panel model. So far so simple. However now I'd like to remove the link in order that I may, depending on the context in which I use the ContactEditPanel, place the submit link at different levels of my overall component hierarchy. For instance in one context I'd like to use to flip between ContactEditPanel and ContactViewPanel with a bar of actions above the current view (edit | save , cancel). Another context would be to use ContactEditPanel in a standalone way (maybe part of a multi-step process) with just a save link below.
I was contemplating refactoring my ContactEditPanel to extends FormComponentPanel rather than Panel as described here but I'm not sure whether this is the right approach and I'm having trouble wrapping my head around this.
Any help would be most appreciated!
Many Thanks,
A
Your using the panel like a FormComponent so extend FormComponentPanel, it will allow you to keep all the validation you write contained to the component and also allow you to reuse it as you wish.
Just think of it as you've created a new FormComponent, like a TextField or DropDownChoice.

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"

jsf popupwindow with a datatable

I have a form which one of it's fields is a code and description, also a button for opening a popup window that contains a list of all of the available codes.
when the user double clickes a row from that table i want to set these values to the code and description. - how can this be done?
Another question, I want to create this popup and table to be initialized dynamically - by that i mean that if i have a few forms in my application, when ever i have a field which has a description i want to be able to open this popup and to see the available list for that field. (every field can be from a diffrent table). is it possible to create something like that? if so, how?
Any help will be appritiated,
Thank's In Advance.
Yes, it is possible. Even more, many component libraries have ready to use popup/dialog components, such as RichFaces with <rich:popupPanel> and PrimeFaces with <p:dialog>.
If you do not want to use a component library for some reason, you would need to create a custom component for this which generates basically an absolutely positioned HTML <div> element with a CSS overlay which get shown/hidden by JS on a particular click/action. The HTML/CSS/JS part should be relatively simple if you are familiar with those languages. The JSF part is somewhat hard if you have never created a custom component before, but it should be possible with a composite component as well, so you could also just create one with pure XHTML. The updating/refreshing can just take place by the usual <f:ajax> means.

Resources