@ActionLayout

Layout hints for actions.

API

ActionLayout.java
@interface ActionLayout {
  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)
  Where hidden() default Where.NOT_SPECIFIED;     (6)
  String named() default "";     (7)
  Position position() default Position.NOT_SPECIFIED;     (8)
  PromptStyle promptStyle() default PromptStyle.AS_CONFIGURED;     (9)
  Redirect redirectPolicy() default Redirect.AS_CONFIGURED;     (10)
}
1 bookmarking

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

2 cssClass

Indicates the css class that an action should have.

3 cssClassFa

Indicates theFont AwesomeCSS class to decorate an action (button or menu item).

4 cssClassFaPosition

Indicates the position of theFont Awesomeicon.

5 describedAs

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

6 hidden

Indicates where in the UI the action should not not be visible.

7 named

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

8 position

For actions that are associated with a property (using either Action#associateWith() or MemberOrder#name() , indicates the positioning of the action’s button relative to the property.

9 promptStyle

How the parameters for this action are prompted, either PromptStyle#DIALOG dialog or PromptStyle#INLINE inline .

10 redirectPolicy

If the action returns its target, then determines whether to update the page or instead to redirect (forcing a re-rendering of a new page).

Members

bookmarking

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

For bookmarkable actions, either org.apache.isis.applib.annotation.BookmarkPolicy#AS_ROOT and org.apache.isis.applib.annotation.BookmarkPolicy#AS_CHILD can be used (they are treated identically).

cssClass

Indicates the css class that an action should have.

For the Wicket viewer, this can be a bootstrap class such as btn-info .

cssClassFa

Indicates theFont AwesomeCSS class to decorate an action (button or menu item).

cssClassFaPosition

Indicates the position of theFont Awesomeicon.

The icon could be rendered on the left or the right of the action button

describedAs

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

hidden

Indicates where in the UI the action should not not be visible.

named

Name of this action (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.

position

For actions that are associated with a property (using either Action#associateWith() or MemberOrder#name() , indicates the positioning of the action’s button relative to the property.

Ignored if the action has not been associated with a property.

promptStyle

How the parameters for this action are prompted, either PromptStyle#DIALOG dialog or PromptStyle#INLINE inline .

redirectPolicy

If the action returns its target, then determines whether to update the page or instead to redirect (forcing a re-rendering of a new page).

Not re-rendering can provide a smoother UI experience.

Supported by the Wicket viewer.

Examples

For example:

public class ToDoItems {
    @Action(semantics=SemanticsOf.SAFE)             (1)
    @ActionLayout(
        bookmarking=BookmarkPolicy.AS_ROOT,
        cssClass="x-key",
        cssClassFa="fa-checkbox",
        describedAs="Mark the todo item as not complete after all",
        hidden=Where.NOWHERE                        (2)
    )
    @MemberOrder(sequence = "1")
    public List<ToDoItem> notYetComplete() {
        ...
    }
}
1 required for bookmarkable actions
2 default value, so could be omitted

As an alternative to using the @ActionLayout annotation, a file-based layout can be used (and is generally to be preferred since it is more flexible/powerful).

Usage Notes

As alternative to using the annotation, the dynamic file-based layout can generally be used instead.

Prompt Style

The promptStyle() element is used to specify whether, when invoking an action associated with a domain object property, the parameters for the action are prompted either in modal dialog box, a (non-modal) sidebar dialog box, or is prompted using an inline panel (replacing the property on the page). For more on sidebar vs modal dialogs, see Wicket viewer features.

The prompt style is influenced by two configuration properties:

  • if the promptStyle() element is set to DIALOG, then a configuration property is used to determine whether to render using a modal dialog or a sidebar:

  • if the attribute is not set at all, then theisis.viewer.wicket.prompt-style configuration property is used to specify the preferred prompt style.

    If the configuration property is not set, then an inline prompt is used.

    And, if this is set but is set to just DIALOG, then the isis.viewer.wicket.dialog-mode configuration property determines which style.

For example:

import lombok.Getter;
import lombok.Setter;

public class Customer {

    @Property(editing = Editing.DISABLED)           (1)
    @Getter @Setter
    private String notes;

    @Action(associateWith="notes")                  (2)
    @ActionLayout(
        promptStyle=PromptStyle.INLINE              (3)
    )
    public Customer updateNotes(String notes) {
        // ...
    }

}
1 property is not editable
2 instead, associate this action with the "notes" property
3 prompt for the action’s parameters using an inline panel.

Exactly one action for a given property can be specified with INLINE_AS_IF_EDIT. Assuming that the corresponding property is not itself editable, this means that the property will be rendered as if it is editable, but the action’s prompt form will be rendered instead. The net effect is that a property conceptually consisting of different parts (eg a name, an address or a date) can be updated using an action that lets each separate part be specified independently.

Positioning

The position() element pertains only to actions that have been associated with properties using @MemberOrder#named. For these actions, it specifies the positioning of the action’s button with respect to the field representing the object property.

The attribute can take one of four values: BELOW, RIGHT, PANEL or PANEL_DROPDOWN.

For example:

import lombok.Getter;
import lombok.Setter;

public class Customer {

    @Property( editing=Editing.DISABLED )
    @Getter @Setter
    private BigDecimal cost;

    @Property( editing=Editing.DISABLED )
    @Getter @Setter
    private String location;

    @MemberOrder( named="cost" )                        (1)
    @ActionLayout(
        named="Update",                                 (2)
        position=Position.BELOW                         (3)
    )
    public Customer updateCost(BigDecimal cost ) {
        // ...
    }

    @MemberOrder( named="location" )
    @ActionLayout(
        named="Update",
        position=Position.BELOW
    )
    public Customer updateLocation(String latitude, String longitude) {
        // ...
    }
}
1 associate the "updateCost" action with the "cost" property
2 give the action an abbreviated name, because the fact that the "cost" property is to be updated is implied by its positioning
3 positioning of the action’s button

The default is BELOW.

If the action is positioned as RIGHT, then the action’s button is rendered to the right of the property’s field, in a compact drop-down.

If the action is positioned as PANEL, then the action’s button is rendered on the header of the panel that contains the property.

And finally, if the action is positioned as PANEL_DROPDOWN, then the action’s button is again rendered on the panel header.

If there are multiple actions associated with a single property then the positioning can be mix’ed-and-match’ed as required. If the PANEL or PANEL_DROPDOWN are used, then (as the screenshots above show) the actions from potentially multiple properties grouped by that panel will be shown together.

Descriptions

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

For example:

public class Customer {
    @ActionLayout(describedAs=
        "Place a repeat order of the last (most recently placed) order")
    public Order placeRepeatOrder(...) { /* ... */ }
}

CSS Styling

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

For example:

public class ToDoItem {
    @ActionLayout(cssClass="x-key")
    public ToDoItem postpone(LocalDate until) { /* ... */ }
    ...
}

The similar @ActionLayout#cssClassFa annotation attribute is also used as a hint to apply CSS, specifically to add Font Awesome icons on action menu items or buttons.

Font Icons

The cssClassFa() element is used to specify the name of a Font Awesome icon name, to be rendered on the action’s representation as a button or menu item. The related cssClassFaPosition() element specifies the positioning of the icon, to the left or the right of the text.

These attributes can also be applied to domain objects to specify the object’s icon.

For example:

public class ToDoItem {

    @ActionLayout(
        cssClassFa="fa-step-backward"
    )
    public ToDoItem previous() {
        // ...
    }

    @ActionLayout(
        cssClassFa="fa-step-forward",
        cssClassFaPosition=ActionLayout.CssClassFaPosition.RIGHT
    )
    public ToDoItem next() {
        // ...
    }
}

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.

Bookmarking

The bookmarking() element indicates if an action (with safe action semantics) is automatically bookmarked.

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

The Web UI (Wicket viewer) supports alt-[ as a shortcut for opening the bookmark panel. Esc will close.

For example:

public class ToDoItems {
    @Action(semantics=SemanticsOf.SAFE)
    @ActionLayout(bookmarking=BookmarkPolicy.AS_ROOT)
    @MemberOrder(sequence = "1")
    public List<ToDoItem> notYetComplete() {
        ...
    }
}

indicates that the notYetComplete() action is bookmarkable.

The enum value AS_CHILD has no meaning for actions; it relates only to bookmarked domain objects.

Hiding actions

The hidden() attribute indicates where (in the UI) the action should be hidden from the user.

It is also possible to use @Action#hidden to hide an action at the domain layer.

For example:

public class Customer {

    @ActionLayout(hidden=Where.EVERYWHERE)
    public void updateStatus() {
        // ...
    }
    ...
}

The acceptable values for the where parameter are:

  • Where.EVERYWHERE or Where.ANYWHERE

    The action should be hidden at all times.

  • Where.NOWHERE

    The action should not be hidden.

The other values of the Where enum have no meaning for a collection.

Names

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

Only use this attribute 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:

public class Customer {
    @ActionLayout(named="Get credit rating")        (1)
    public CreditRating obtainCreditRating() {
        // ...
    }
}
1 "get" normally indicates a property rather than an action.

Alternatives

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

Smoother UI

Often an action, when invoked, will return the target (in other words, will "return this"). The redirectPolicy() element is used to control how the object is re-rendered.

There are three options:

  • if set to ONLY_IF_DIFFERS, then the existing web page will not be re-rendered, rather it will be updated in-place (using Ajax).

    This makes for a smoother UI.

    Any properties with @PropertyLayout#repainting set to NO_REPAINT are then not updated.

  • if set to EVEN_IF_SAME, then a redirect occurs and a new web page is rendered.

  • if set to AS_CONFIGURED, then the default behaviour is as specified by the isis.viewer.wicket.redirectEvenIfSameObject configuration property).

One use case for choosing EVEN_IF_SAME is if the action "returning this" is intended in some way to require that the object use a different layout, as per multiple layout support, as specified using the layout() method.

For example:

import lombok.Getter;
import lombok.Setter;

public class Customer {

    @Getter @Setter
    @PropertyLayout(hidden=ALWAYS)
    private String layout;

    public String layout() {                (1)
        return layout;
    }

    @ActionLayout(
        redirect=EVEN_IF_SAME               (2)
    )
    public Customer switchToEditMode() {
        setLayout("edit");
        return this;
    }
}
1 specifies the alternate layout to use, eg Customer-edit.layout.xml.
2 even though this action returns the same target object, still re-render the page.

If switchToEditMode() action is invoked, then the UI will attempt to render the customer using a Customer.layout.edit.xml layout file (instead of the default Customer.layout.xml).