UI Extension Points
Explanation
A UI extension point (UIXP) is a named place in a rendered page that an extension can add content to without owning the code that renders it, a mechanism the UIExtension Module provides to the whole platform. The Applications Panel, the tabs below a page and the user menu are built this way: each one is an id, and what it shows is whatever is registered against that id when the page is rendered.
Nothing Declares a Point
A point exists because something asks for its contributions by id. From wiki syntax, which inserts them one after another:
{{uiextensions extensionPoint="org.xwiki.platform.panels.Applications"/}}From script, which can lay them out instead:
{{velocity}}
#foreach ($uix in $services.uix.getExtensions('org.xwiki.platform.panels.Applications'))
* $services.rendering.render($uix.execute(), 'xhtml/1.0')
#end
{{/velocity}}The id is a plain string that nothing validates, so a point nobody contributes to and a point whose id is misspelled both render the same nothing. The points a release offers therefore cannot be read off the code, which is why each one gets a documentation page: All Bundled UI Extension Points lists the ones XWiki ships, UI Extension Points (Extensions) the ones an installed extension brings, and the older Available Extension Points list still holds the points neither page covers yet.
How a Contribution Reaches the Point
The lookup goes through the context component manager, so a contribution registered for the current user or the current wiki is found only there, and the same point rendered on another wiki of the farm does not see it. A component implementing UIExtensionManager and registered under the point's own id replaces that lookup for that one point, which is how a point that computes its contributions rather than collecting them is built.
Two Ways to Contribute
A contribution is either an XWiki.UIExtensionClass object on a wiki page, which needs no build and no restart, or a Java component implementing the UIExtension role. XWiki turns the object into one of those components, so both arrive at the same place. The object holds:
| Field | What it holds |
|---|---|
| extensionPointId | The id of the point this contribution answers. |
| name | The id of the contribution itself, by which the select, exclude and sortByCustomOrder filters address it. |
| content | The wiki syntax executed when the point is rendered, with the rights of the page's author. |
| parameters | The values the point reads, one key=value per line. |
| scope | Current User, Current Wiki or Global, which decides the component manager the contribution is registered in and therefore who sees it. |
Order Is the Caller's Decision
The manager returns the contributions in no guaranteed order, and the uiextensions macro inserts them as it receives them. A point that needs an order asks for it, by passing the hint of a UIExtensionFilter component and the argument that filter takes:
$services.uix.getExtensions('org.xwiki.platform.panels.Applications', {'sortByParameter': 'order'})The bundled filters are sortById, sortByParameter, sortByCustomOrder, select and exclude. A point that sorts on a parameter says so in its own documentation, since that parameter is part of what it asks its contributions for.
FAQ
Why does my contribution not appear at its point?
The usual causes are a misspelled extensionPointId, which nothing reports, and a scope narrower than the wiki the page is rendered on.
With whose rights does a wiki contribution run?
With those of the author of the page holding the XWiki.UIExtensionClass object, not those of the reader, so that page needs the rights its content uses.
Can two extensions contribute to the same point?
Yes, and all of them are rendered. That is what makes a point an extension point rather than a slot one extension takes over.
More
To find more about the current topic, you can search or use the table below and filter the columns to narrow your choices.