@DomainObjectLayout

Layout hints for domain objects.

API

DomainObjectLayout.java
@interface DomainObjectLayout {
  BookmarkPolicy bookmarking() default BookmarkPolicy.NOT_SPECIFIED;     (1)
  String cssClass() default "";     (2)
  String cssClassFa() default "";     (3)
  CssClassFaPosition cssClassFaPosition() default CssClassFaPosition.LEFT;     (4)
  String describedAs() default "";     (5)
  String named() default "";     (6)
  int paged() default -1;     (7)
  String plural() default "";     (8)
  Class<? extends CssClassUiEvent<?>> cssClassUiEvent() default CssClassUiEvent.Default.class;     (9)
  Class<? extends IconUiEvent<?>> iconUiEvent() default IconUiEvent.Default.class;     (10)
  Class<? extends LayoutUiEvent<?>> layoutUiEvent() default LayoutUiEvent.Default.class;     (11)
  Class<? extends TitleUiEvent<?>> titleUiEvent() default TitleUiEvent.Default.class;     (12)
}
1 bookmarking

Whether (and how) this domain object can be bookmarked in the UI.

2 cssClass

Indicates the css class that a domain class (type) should have, to allow more targeted styling in application.css .

3 cssClassFa

Indicates theFont AwesomeCSS class to decorate an domain object.

4 cssClassFaPosition

Indicates the position of theFont Awesomeicon. The icon could be rendered on the left or the right of the object’s title.

5 describedAs

Description of this class, eg to be rendered in a tooltip.

6 named

Name of this class (overriding the name derived from its name in code).

7 paged

The page size for instances of this class when rendered within a table.

8 plural

The plural name of the class.

9 cssClassUiEvent

Which subclass of CssClassUiEvent should be used to obtain a CSS class.

10 iconUiEvent

Which subclass of IconUiEvent should be used to obtain an icon.

11 layoutUiEvent

Which subclass of LayoutUiEvent should be used to obtain a layout.

12 titleUiEvent

Which subclass of TitleUiEvent should be used to obtain a title.

Members

bookmarking

Whether (and how) this domain object can be bookmarked in the UI.

cssClass

Indicates the css class that a domain class (type) should have, to allow more targeted styling in application.css .

cssClassFa

Indicates theFont AwesomeCSS class to decorate an domain object.

cssClassFaPosition

Indicates the position of theFont Awesomeicon. The icon could be rendered on the left or the right of the object’s title.

This attribute is currently ignored by Isis viewers.

describedAs

Description of this class, eg to be rendered in a tooltip.

named

Name of this class (overriding the name derived from its name in code).

A typical use case is if the desired name is a reserved Java keyword, such as default or package.

paged

The page size for instances of this class when rendered within a table.

If annotated on a collection, then the page size refers to parented collections (eg Order#lineItems ).

If annotated on a type, then the page size refers to standalone collections (eg as returned from a repository query).

plural

The plural name of the class.

cssClassUiEvent

Which subclass of CssClassUiEvent should be used to obtain a CSS class.

This subclass must provide a no-arg constructor; the fields are set reflectively.

iconUiEvent

Which subclass of IconUiEvent should be used to obtain an icon.

This subclass must provide a no-arg constructor; the fields are set reflectively.

layoutUiEvent

Which subclass of LayoutUiEvent should be used to obtain a layout.

This subclass must provide a no-arg constructor; the fields are set reflectively.

titleUiEvent

Which subclass of TitleUiEvent should be used to obtain a title.

This subclass must provide a no-arg constructor; the fields are set reflectively.

Examples

For example:

@DomainObjectLayout(
    cssClass="x-key",
    cssClassFa="fa-checklist",
    describedAs="Capture a task that you need to do",
    named="ToDo",
    paged=30,
    plural="ToDo List")
)
public class ToDoItem {
    ...
}

Note that there is (currently) no support for specifying UI hints for domain objects through the dynamic .layout.xml file (only for properties, collections and actions are supported).

Usage Notes

Descriptions

The describedAs() element is used to provide a short description of the domain object to the user. In the Web UI (Wicket viewer) it is displayed as a 'tool tip'.

For example:

@DomainObjectLayout(
    describedAs = "A customer who may have originally become"
                + " known to us via the marketing system or who may"
                + " have contacted us directly."
 )
public class ProspectiveSale {
   ...
}

CSS Styling

The cssClass() element can be used to render additional CSS classes in the HTML (a wrapping <div>) that represents the domain object. Application-specific CSS can then be used to target and adjust the UI representation of that particular element.

For example:

@DomainObject
@DomainObjectLayout(
    cssClass="x-core-entity"
)
public class ToDoItem { /* ... */ }

The similar @DomainObjectLayout#cssClassFa() element is also used as a hint to apply CSS, but in particular to allow Font Awesome icons to be rendered as the icon for classes.

Font Awesome Icons

The cssClassFa() element is used to specify the name of a Font Awesome icon name, to be rendered as the domain object’s icon.

If necessary the icon specified can be overridden by a particular object instance using the iconName() method.

For example:

@DomainObjectLayout(
    cssClassFa="fa-check-circle"
)
public class ToDoItem {
    // ...
}

There can be multiple "fa-" classes, eg to mirror or rotate the icon. There is no need to include the mandatory fa "marker" CSS class; it will be automatically added to the list. The fa- prefix can also be omitted from the class names; it will be prepended to each if required.

The related cssClassFaPosition element is currently unused for domain objects; the icon is always rendered to the left.

The similar @DomainObjectLayout#cssClass() element is also used as a hint to apply CSS, but for wrapping the representation of an object or object member so that it can be styled in an application-specific way.

Names

The named() element explicitly specifies the domain object’s name, overriding the name that would normally be inferred from the Java source code.

We recommend that you only use this element when the desired name cannot be used in Java source code. Examples of that include a name that would be a reserved Java keyword (eg "package"), or a name that has punctuation, eg apostrophes.

For example:

@DomainObjectLayout(
   named="Customer"
)
public class CustomerImpl implements Customer{
   // ...
}

Plural form

When Apache Isis displays a standalone collection of several objects, it will label the collection using the plural form of the object type. By default the plural name will be derived from the end of the singular name, with support for some basic English language defaults (eg using "ies" for names ending with a "y").

For irregular plurals it’s possible to specify a plural form using the plural element.

For example:

@DomainObjectLayout(plural="Children")
public class Child {
    // ...
}

i18n

The framework also provides a separate, powerful mechanism for internationalization.

Bookmarks

The bookmarking() element indicates that an entity is automatically bookmarked.

In the Web UI (Wicket viewer), a link to a bookmarked object is shown in the bookmarks panel, top right.

For example:

@DomainObject(bookmarking=BookmarkPolicy.AS_ROOT)
public class ToDoItem ... {
    ...
}

indicates that the ToDoItem class is bookmarkable:

It is also possible to nest bookmarkable entities. For example:

bookmarking nested

For example, the Property entity "[OXF] Oxford Super Mall" is a root bookmark, but the Unit child entity "[OXF-001] Unit 1" only appears as a bookmark but only if its parent Property has already been bookmarked.

This is accomplished with the following annotations:

@DomainObject(bookmarking=BookmarkPolicy.AS_ROOT)
public class Property {
    // ...
}

and

@DomainObject(bookmarking=BookmarkPolicy.AS_CHILD)
public abstract class Unit {
    // ...
}

The nesting can be done to any level.

Paging

The paged() element specifies the number of rows to display in a standalone collection, as returned from an action invocation.

The RestfulObjects viewer currently does not support paging. The Web UI (Wicket viewer) does support paging, but note that the paging is performed client-side rather than server-side.

We therefore recommend that large collections should instead be modelled as actions (to allow filtering to be applied to limit the number of rows).

For example:

@DomainObjectLayout(paged=15)
public class Order {
    // ...
}

It is also possible to specify a global default for the page size of standalone collections, using the isis.applib.annotation.domain-object-layout.paged configuration property.

UI Events

Whenever a domain object is to be rendered, the framework fires off a number of various events to allow subscribers to influence the visual appearance of that domain object:

  • a CSS class UI event

    to obtain a CSS class to use in any wrapping <div>s and <span>s that render the domain object.

  • an icon UI event

    to obtain an icon (name) for the object (if possible)

  • a layout UI event

    to obtain an alternative layout name with which to render the domain object.

  • a title UI event

    to obtain a title for the object

The framework has a built-in event class (for each UI hint) that is raised by default; for example a TitleUiEvent.Default is raised to obtain a title for the object. Subscribers subscribe through the EventBusService and can use obtain a reference to the domain object from the event. From this they can, if they wish, specify the corresponding UI hint.

This basic model can be influenced in a couple of ways:

  • first, it is also possible to suppress any events from being emitted using a configuration property (a different config property exists each lifecycle hook).

  • second, an element on @DomainObjectLayout annotation (for each UI hook) allows a different subtype event types to be emitted instead

    This allows subscribers to more targeted as to the events that they subscribe to.

The type of this event can be changed using various xxxUiEvent elements of @DomainObjectLayout. This allows subscribers to be more precise as to the domain objects that they will target.

The framework also provides convenience "Doop" and a "Noop" event classes, that provoke these behaviours:

  • if the appropriate DomainObject' element is set to the "Doop" subclass, then this will event will be fired

    this is a convenient way of ensuring an event is fired even if the hook has been disabled globally, but without the hassle of defining a custom event type

  • if set to the "Noop" subclass, then an event will not be fired.

If the domain object implements the corresponding reserved method directly (for example title(), then that will take precedence.

The table below summarises all the UI event hooks:

UI hint

Config property

@DomainObjectLayout override

Framework event types

Reserved method

CSS class

CssClassUiEvent.Default
CssClassUiEvent.Doop
CssClassUiEvent.Noop

Icon Name

IconUiEvent.Default
IconUiEvent.Doop
IconUiEvent.Noop

Layout

LayoutUiEvent.Default
LayoutUiEvent.Doop
LayoutUiEvent.Noop

Title

TitleUiEvent.Default
TitleUiEvent.Doop
TitleUiEvent.Noop

For example:

@DomainObjectLayout(
    iconUiEvent=ToDoItemDto.CssClassUiEvent.class,
    titleUiEvent=ToDoItemDto.TitleUiEvent.class
)
public class ToDoItemDto {
    public static class CssClassUiEvent
        extends org.apache.isis.applib.events.ui.CssClassUiEvent<ToDoItemDto> { }
    public static class TitleUiEvent
    extends org.apache.isis.applib.events.ui.TitleUiEvent<ToDoItemDto> { }
    ...
}

Subscribers

Subscribers can be either coarse-grained (if they subscribe to the top-level event type):

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

@Service
public class SomeSubscriber {
    @EventListener(CssClassUiEvent.class)
    public void on(CssClassUiEvent ev) {
        if(ev.getSource() instanceof ToDoItemDto) {
            ...
        }
    }
}

or can be fine-grained (by subscribing to specific event subtypes):

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

@Service
public class SomeSubscriber {
    @EventListener(ToDoItemDto.CssClassUiEvent.class)
    public void on(ToDoItemDto.CssClassUiEvent ev) {
        ...
    }
}

The subscriber should then use the appropriate method —  CssClassUiEvent#setCssClass(…​)  — to actually specify the CSS class to be used.