A content view is a notion to define all the elements needed to get a list of items and perform their rendering. The most obvious use case is the listing of a folderish document content, where we would like to be able to:
The Nuxeo Content View framework makes it possible to define such an object, by registering content views to the service. Here is a sample contribution, that will display the children of the current document:
The content view query
The "coreQueryPageProvider" element makes it possible to define whet query will be performed. Here it is a query on a core session, using a pattern with one parameter.
This element accepts any number of property elements, defining needed context variables for the page provider to perform its work. The "coreSession" property is mandatory for a core query to be processed and is bound to the core session proxy named "documentManager" available in a default Nuxeo application.
This element also accepts any number of "parameter" elements, where order of definition matters: this EL expression will be resolved when performing the query, replacing the '?' characters it holds.
The main difference between properties and parameters is that properties will not be recomputed when refreshing the provider, whereas parameters will be. Properties will only be recomputed when resetting the provider.
The "sort" element defines the default sort, that can be changed later through the interface. There can be any number of "sort" elements. The "sortInfosBinding" element can also be defined: it can resolve an EL expression in case the sort infos are held by a thirs party instance (document, seam component...) and will be used instead of the default sort information if not null or empty. The EL expression can either resolve to a list of
org.nuxeo.ecm.core.api.SortInfo instances, or a list of map items using keys "sortColumn" (with a String value) and "sortAscending" (with a boolean value).
The "pageSize" element defines the default page size, it can also be changed later. The "pageSizeBinding" element can also be defined: it can resolve an EL expression in case the page size is held by a third party instance (document, seam component...), and will be used instead of the default page size if not null.
The optional "maxPageSize" element can be placed at the same level than "pageSize" and is available since version 5.4.2. It makes it possible to define the maximum page size so that the content view does not overload the server when retrieving a large number of items. When not set, the default value "100" will be used: even when asking for all the results with a page size with value "0" (when exporting the content view in CSV format for instance), only 100 items will be returned. Since 5.6 (and some previous hotfixed versions, see NXP-9052) this is configurable globally using the runtime property "nuxeo.pageprovider.default-max-page-size".
Since version 5.6, you can set a maximum number of results. This is useful for performance reasons, because it takes time to get the total number of results (and thus the number of pages). If there are more results than the limit, then the number of pages will be unknown, nevertheless you can still navigate to the next page if it exists.
To set this limit you need to add a "maxResults" parameter to "coreQueryPageProvider", either using an integer value or one of the following keywords:
- DEFAULT_NAVIGATION_RESULTS: Used by most of the navigation page provider, the default is 200 and it can be overridden using Java options:
- PAGE_SIZE: this is useful when you are interested in a single page or if you don't need a total count.
This kind of core query can also perform a more complex form of query, using a document model to store query parameters. Using a document model makes it easy to :
- use a layout to display the form that will define query parameters
- save this document in the repository, so that the same query can be replayed when viewing this document
Here is an example of such a registration:
This definition holds a "whereClause" element, stating the search document type and predicates explaining how the document model properties will translated into a NXQL query. It can also state a "fixedPart" element that will added as to the query string. This fixed part can also take parameters using the '?' character and "parameter" elements.
The "searchLayout" element defines what layouts needs to be used when rendering the search document model: it will be in charge of displaying the search form. Since 5.5, this element accepts a "filterDisplayType" attribute. When set to "quick", it'll display a form showing only the first row of the layout, visible directly above the content view results. The whole filter form is then displayed in a popup. Otherwise, the default rendering is used, and the filter form is visible in a foldable box.
Since 5.4.2, the "showFilterForm" element makes it possible to show this form above the content view results.
Since 5.4.2, the "searchDocument" variable can be used in EL expressions to bind the page size, the sort infos and the result columns to the search document properties.
The content view result layouts
The result layouts control the display of resulting documents. It states different kinds of rendering so that it's possible to switch between them. They also accept a title and an icon, useful for rendering.
The layout configuration is stanadard and has to follow listing layouts configuration standards. The layout template, as well as widgets displaying selection checkboxes, need to perform an Ajax selection of documents, and re-render the action buttons region.
The content view selection list
The "selectionList" element will be used to fill the document list with given name.
Selection is done through ajax, so that selection is not lost when not performing any action thanks to this selection.
The content view actions
The "actions" element can be repeated any number of times: it states the actions category to use to display buttons applying to this table ("copy", "paste", "delete",...). Each "actions" element will generate a new row of buttons.
These actions will be displayed under the table in default templates, and will be re-rendered when selecting an item of the table so that they are enabled or disabled. this is performed using adequate filters, performing checks on selected items.
The "searchDocument" element can be filled on a content view using an EL expression: it will be used as the search document model. Otherwise, a bare document will be generated from the document type.
Sample usage, showing how to add a clause to the search depending on title set on the current document (will watch non deleted document with the same title):
The "resultColumns" element can be filled on a content view using an EL expression: it will be used to resolve the list of selected columns for the current result layout. If several result layouts are defined, they should be configured so that their rows are always selected in case the selected column names do not match theirs.
Sample usage, showing how to reuse the same selected colums than the one selected on the advanced search page:
Additional rendering information can also be set, to be used by templates when rendering the content view:
The element "showTitle" is available since version 5.4.2. It can be used to define a title for the content view, without displaying it on the default rendering. It can also be used when exporting the content view in CSV format, for instance.
The elements "emptySentence" and "translateEmptySentence" are available since version 5.4.2. They are used to display the message stating that there are no elements in the content view.
The elements "showPageSizeSelector" and "showRefreshCommand" are available since version 5.4.2. They are used to control the display of the page size selector, and of the "refresh current page" button. They both default to true.
The "cacheKey" element, if filled, will make it possible to keep content views in cache in the current conversation. It accepts EL expressions, but a static cache key can be used to cache only one instance.
The "cacheSize" element is useful to use a queue of cached instances. In the example, 10 instances of content views with a different cache key will be kept in cache. When the 11th entry, with a new cache key, is generated, the first content view put in the cache will be removed, and will need to be re-generated again. This cache configuration will make it possible to navigate to 10 different folderish document pages, and keep the current page, the current sort information, and current result layout.
When caching only one instance, setting the "cacheSize" element to more than "1" is useless. Caching only one instance can be useful when several features need to retrieve information from the same content view.
If a cache key is given, but no cache size is set, "5" will be used by default. Using "0" means no caching at all (and the cache key will be ignored).
Caching is done by a Seam component named "contentViewActions". Although the cache key, cache size and events configurations handle the most common use cases, it is sometimes useful to call this bean methods directly when forcing a refresh.
The "refresh" and "reset" elements configurations make it possible to refresh/reset this content view when receiving the listed Seam event names. Only "documentChanged" and "documentChildrenChanged" are handled by default, but it is possible to react to new events by adding a method with an observer on this event on a custom Seam component, and call the method "contentViewActions.refreshOnSeamEvent(String seamEventName)" or "contentViewActions.resetPageProviderOnSeamEvent(String seamEventName)".
Refresh will keep current settings, and will force the query to be done again. Reset will delete content views completely from the cache, and force complete re-generation of the content view, its provider, and the search document model if set.
Before 5.7, selection actions were misbehaving when using a cache of size "0", so content views with selections actions needed a cache size of at least "1". Since 5.7 (and 5.6-HF02), when using value "0", the content view is cached anyhow, but its page provider is refreshed every time it is rendered.
As this behaviour is costly, using refresh events can be enough most of the time. But it is not possible to trigger a refresh for other users when using Seam events, so this configuration makes it possible to make sure the content view is up to date when other users may have an impact on its content.
Document content views
It is possible to define content views on a document type. This makes it easier to define folderish documents views.
Here is the default configuration of content views for Nuxeo folderish documents:
The "document_content" content view will be displayed on this folder default view, and the "document_trash_content" content view will be displayed on the trash tab.
The "category" attribute is filled from xhtml templates to render all content views defined in a given category.
The "showInExportView" attribute is used to check whether this content view should be displayed in the document export view (and PDF export)
If several content views are filled in the same category, both will be displayed on the same page.
Rendering is done using methods set on Generic Seam components: "contentViewActions" (
org.nuxeo.ecm.webapp.contentbrowser.ContentViewActions) and "documentContentViewActions" (
org.nuxeo.ecm.webapp.contentbrowser.DocumentContentViewActions) to handle document content views categories.
A typical usage of content views, to render the results, would be:
/incl/content_view.xhtml handles generic rendering of the given content view (content view title, pagination, result layout selection, list rendering, actions rendering) . It inserts names region that can be overriden when using the "ui:decorate" tag.
The current version of this template is here: https://github.com/nuxeo/nuxeo-jsf/blob/5.7-SNAPSHOT/nuxeo-platform-webapp-base/src/main/resources/web/nuxeo.war/incl/content_view.xhtml
Here is the sample rendering of the search form defined on a content view named "document_content_filter":
Here is a typical way of refreshing or resetting a provider named "advanced_search" from the interface: