xpages property file vs administration menu for dropdown list - xpages

What is the best practice for populating dropdown lists in case of XPages application:
the list items managed in the administration menu and displayed using #DbColumn/#DbLookup
the list items stored in property files and retrieved using SSJS
For better performance which can be the preferred solution in case of:
n. of list items<10
n. of list items<100
n. of list items<1000
n. of list items<10000

Neither nor!
A VERY smart way is to have one (or two) beans that hold all the properties you would be eventually looking for. If that are global values an applicationScope is the right place. For user specific ones it is the sessionScope. Your value population will be easy in the XPage: AppSetup.departments (that is EL code, not SSJS!) where AppSetup is the managed bean name and departments translates into .getDepartments();
You can start with a simple lookup inside the bean and later add caching and alternate storage (e.g. a MIMEDoc) as you deem fit. Since your "contract" are the public methods you can optimize internally to your hearts desire.
Here is a SSJS version of the caching lookup, but you want to go for the bean since it allows you to use EL which adds a little extra speed.
One remark: you know that a kitten must die every time a dropdown list has more than 100 entries. That so NOT suitable for UX. For large values use a grid with search capabilities or other UX elements.

Related

Lookup for large list on xPage

I have a list of approx 10K entries (and growing) I need to be able to reference in an xPages app. I have had lookup limitations using #DbLookup, so have looked at other options. Unfortunately I continue to run into these limitations.
I am currently loading the lookup list into a session scope variable on page load (which has performance impacts), and the reference the scoped variable for the combo box.
I am using the following simple process to load the list for the combo box. This, however, is also running into limitations.
var lookupView:NotesView = database.getView("LookupView");
sessionScope.lookupList = lookupView.getColumnValues(0) + "|" + lookupView.getColumnValues(4);
I would like a method to perform a lookup that can handle the larger list (main priority) with performance being number 2. The page is used by a limited number of users with the function being most important.
Take a look at this code snippet "Pure Java version of DbLookup & DbColumn, with cache, sort and unique" and either use it directly or use it as inspiration.
You should consider storing the list in application scope since it seems that the list is the same for all users. This means that you need to change the code in the code snippet to use applicationScope instead of sessionScope.
I doubt your users want or need to pick some value from combo with 10k+ lines.
Rethink your approach, you can use autocomplete feature with dynamic filter/search in live view (no scoped variable needed), as pointed by Mark. Another approach is to divide that values into some groups and split that combo to two or three with cascading choose/lookup function. First one picks one group, second one looks up only options from first group. That way you probably won't hit that #DbLookup limitations.

filtering/searching on a repeat control

In my application, i would like to replace a viewpanel with a repeat control.
However, part of the functionality is there is a UI aspect that allows users to select certain fields (that correspond to the view), and only display the documents that match. The view is doing a filter that allows users to select aspects of the view to create a search (the code is under search of the view) that allows the view panel to be updated with the results of the search.
one of the things that is curious is that the viewpanel has a value of "#{javascript:view2}" vice an actual view name.
The viewpanel defines the search view and the ...
I'd like to be able to apply that same functionality to the repeat control. I don't see those attributes on the repeat control... Any pointers? Its been a while since i've worked with xpages... long enough that I've forgotten a lot already....
TIA !
Read this blog post I did a while back, it should explain what you need.
The view panel doesn't filter anything, it just displays rows from a datasource, same as a repeat control. Indeed you can add components to a ViewPanel's column, pulling from the current row by adding a var property to the dominoView datasource.
The view is bound to #{javascript:view2} (which would be better done by binding to #{view2} - there's no need to call SSJS here). view2 is a dominoView datasource somewhere on your page. The datasource is a wrapper that has properties to capture the settings for filtering and searching that you want to do. At runtime, they are calculated and changes the ViewEntries in the datasource.
Finally there's is the underlying Domino View object available also to LotusScript. This holds and will always hold all entries. The dominoView datasource queries that using the filtering and searching properties and retrieves a ViewEntryCollection or a ViewNavigator.
So whether you use a View Panel, Repeat Control, Data View or whatever else, those are just components to visually represent a collection of ViewEntries or Documents. All can be bound to a dominoView datasource. Where repeat controls and Data Views give you extra power is you can bind them to any kind of collection, not just a dominoView datasource (e.g. DocumentCollection, ViewEntryCollection, multi-value field, Java collection, etc).
I often find that doing the searches in Java and then passing the results to the repeat as a List work better and allow more options. I can get all the information I need in Java and load that into a Map or Tree. This gives me the ability to do custom sorting in the Java class and also to combine data from other views/databases easily. Since the data is now in memory it gets reloaded fast. The only thing you have to watch for is the size of the data. If you have a view with many entries (10K?) you might not want to load everything into memory...
Howard
I'm not sure if you've found a solution yet, but consider using jQuery dataTables. Oliver Busse wrote a very detailed blog post about integrating dataTables into XPages.
To get the specific formatting, I used a repeat control to include the "td", "tr" and "thead" attributes Oliver listed in his blog post.

Can i get all components of an xsp document in xpages?

I have a simple document with 3 fields and 1 rich text field. I also have an xpage with 3 simple edit box controls and 1 rich text. The name of my NotesXSPDocument is document1.
Question 1:
Can i get a vector with all the controls of the xsp document? for example, instead of using getComponent("fld1"), getComponent("fld2") ... etc, can i use something like getAllComponents() or document1.getControls()? These methods do not exist of course so i am asking if there is a way to do it. I know i can get all items of a document (not XSP) by calling document1.getDocument().getItems(). IS there anything similar for xsp?
Question2:
Lets say we can get a vector as i described above. Then if i iterate through this vector to get each control's value, is there a method to check if it is rich text or simple text field?
Technically, yes, but not readily and this is one of those situations where there's likely a better way to approach whatever underlying problem it is you want to solve.
Nonetheless, if you're looking to get a list of inputs on the page, XspQuery is your friend: http://avatar.red-pill.mobi/tim/blog.nsf/d6plinks/TTRY-96R5ZT . With that, you could use "locateInputs" to get a List of all the inputs on the page, and then check their value method bindings to see if the string version is referencing your variable name. Error-prone and not pretty, but it'd work. Since they're property bindings, I don't think the startsWith filter in there would do what you want.
Alternatively, you could bind the components to something in a Java class from the start. I've been doing just such a thing recently (for a different end) and initially described it here: https://frostillic.us/f.nsf/posts/my-black-magic-for-the-day . The upshot is that, with the right cleverness for how you do your binding="" property, you could get a list of all the components that reference a property of a given object.
As for the second part of the question, if you DO get a handle on the components one way or another, you can check to see if it's a rich text control by doing "component instanceof com.ibm.xsp.UIInputRichText".
A bit complex but yes. facesContext.getViewRoot() is an UIViewRoot object so it has List<UIComponent> getChildren() method which returns its children.
However, since it's a tree-structure, some of its children will have additional children components. You have to traverse the entire tree to build a list of components you want to see.
For types, you can decide what type a component is by its class. For instance, UIInput is a text box, etc.

Can (or should) I use one view for multiple View Controls

In traditional Notes programming it was a best practice to use hidden views for things like DbLookups and non-hidden views for user facing views. This way you wouldn't get a request for a user to add a field to a view and break your lookups. Keep presentation separated form logic.
I still follow this in Xpages. But I was wondering if we can (or should) reuse hidden views that are used for data sources for more than one presentation view. In other words should there be a one to one correspondence between a view and a view type control. Are there limitations to having a many to one relationship?
I think that in the XPages world... assuming it's 100% an XPages app there's much less need for using Views as "presentation". Since you can change things in your view and repeat controls for the presentation.
So you might end up having 1 view with many more fields then you need but that feeds multiple view controls and you're just showing the columns of interest etc. The iffy part is if you're going to use the view control for sorting columns and all that. I don't actually use the view control much. I find it too limiting. I prefer repeat controls.
So to answer you're question I think you absolutely should reuse views as many times as you want. From a performance perspective the less views the better typically I think.
These days I do less with views overall. I make Java Objects to represent my document. So I'll use some views to find the correct documents and then push them into java objects. Then in Java I'll use code to sort things different ways and send that back out to a repeat control. Works very well and that lets me cut down on views. BUT if you're doing this with 3,000+ documents... there can be some delays for the initial injection so in some situations I might have to get back to actually touching the views just to get better performance.
There is no need to maintain a one-to-one relationship between View design elements and View panel controls in an XPages application, and IMHO you shouldn't.
Consider a traditional Notes client application with only one Form design element and many, many View design elements. When your main/only presentation tools are the Form and the View elements you tend to get a lot of Views to meet the various presentation requirements of the application. Of course each added View will spawn an Index, increasing the size and decreasing performance in the application.
One great feature of XPages is the separation of the data and the presentation layer. This allows you to reuse the same Domino View data source on several XPages with different presentation requirements -- each XPage displaying a different set of columns or uses a different iterator control to display the view data (xp:viewPanel, xp:repeat, xp:dataTable, xe:dataView, xe:dynamicViewPanel, or xe:djxDataGrid).
When I'm developing a new XPages application with no traditional Notes client access I find that I tend to create fewer, flatter, and often wider views (i.e. more columns).
I'm getting wider views with more columns because its more efficient to return column values then field values in the underlying document. All of the iterator controls have a var variable to address the entries in the Domino View data source, even xe:djxDataGrid via its REST Service. When using a Domino View data source I tend to set var="viewEntry" to reflect its NotesXspViewEntry type.
So, when there is no column for the field values I need to return (say to a Computed Field in a View Column or in another facet of an iterator control) I have to get it from the underlying document like so:
<xp:text escape="true" id="computedField3">
<xp:this.value><![CDATA[#{javascript:
return viewEntry.getDocument().getItemValueString("City") + ", " + viewEntry.getDocument().getItemValueString("State");
}]]></xp:this.value>
</xp:text>
But if I just tack on the City and State columns to my View design for the Domino View data source then the following code runs faster:
<xp:text escape="true" id="computedField2">
<xp:this.value><![CDATA[#{javascript:
return viewEntry.getColumnValue("City") + ", " + viewEntry.getColumnValue("State");
}]]></xp:this.value>
</xp:text>
And faster still is the EL equivalent:
<xp:text escape="true" id="computedField1"
value="#{viewEntry.City}, #{viewEntry.State}">
</xp:text>
Since I address the View column in my XPages code by programmatic name and not by position, adding new columns to my View design as I need them doesn't seem to break anything (at least not yet ;)

NSArrayController that is sorted and unique (no duplicates) for use in a pop-up in a core-data app

I have core data app with an entity OBSERVATION that has as one of its attributes DEALNAME.
I want to reference through Interface Builder or by making custom modifications to an NSArrayController a list of unique sorted dealnames so that I can use them in a pop-up.
I have attempted to use #distinctUnionOfSets (and #distinctUnionOfArrays) but am unable to locate the proper key sequence.
I can sort the ArrayController by providing a sort descriptor, but do not know how to eliminate duplicates.
Are the #distinct... keys the right methodology? It would seem to provide the easiest way to optimize the use of IB.
Is there a predicate form for removing duplicates?
Or do I need to use my custom controller to extract an NSSet of the specific dealnames, put them back in an array and sort it and reference the custom array from IB?
Any help would be appreciated. I am astounded that other have not tried to create a sorted-unique pop-up in tableviews.
You need to take a look at -[NSFetchRequest returnsDistinctResults]. That is the level you need to be handling the uniquing of data.
Although I do not have a definitive answer for you, I think there are two ways you can go about it.
The way you already started. You need to bind the contents array of the PopUp button, not just against the arrayController.arrangedObjects, but continue on the path and somehow filter only objects with distinct "DealName"s. This means - the arrayController presents ALL the entities (and may sort them for you) but the PopUp button will have its contents filter via some sophisticated binding to the array controller.
Make your filtering at the ArrayController level (as suggested in another answer here). Here it depends how you set up the array controller. If It is set up to use an "Entity" (vs. "Class") which means the array controller will fetch CoreData entities directly - you can modify its "Fetch" to only bring a subset of the "OBSERVATION" entities with distinct values of "DEALNAME". I don't know how to control WHICH entities are filtered out in this case. Otherwise, you can setup the arrayController to work with "Class" objects, and then you can fetch the entities yourself (in code) and populate the arrayController programmatically, with just the entities you like.
In the second option, the Popup button should be bound normally to the arrayController's arrangedObjects.

Resources