Skip to content

Actions

Actions represent operations that users can trigger — create, update, delete, or custom domain-specific actions.

Defining Actions

typescript
import { action, Position, Scope, Icon } from '@anhanga/core'

const PersonSchema = schema.create('person', {
  fields: { /* ... */ },
  actions: {
    create: action().primary().order(999).positions(Position.footer).scopes(Scope.add),
    cancel: action().start().order(1).positions(Position.footer).scopes(Scope.add, Scope.edit),
    destroy: action().destructive().positions(Position.footer, Position.row).excludeScopes(Scope.add),
    custom: action().icon(Icon.Send).warning().positions(Position.footer).scopes(Scope.add),
  },
})

Variants

Actions have visual variants that determine their appearance:

MethodDescription
.primary()Primary action (submit, save)
.secondary()Secondary action
.destructive()Destructive action (delete)
.warning()Warning action
.success()Success variant
.info()Informational variant
.muted()Muted/subtle variant
.accent()Accent variant

Positioning

Control where actions appear with .positions():

typescript
action().positions(Position.top)       // top of the page (e.g., "Add" button)
action().positions(Position.footer)    // form footer
action().positions(Position.floating)  // floating action button
action().positions(Position.row)       // table row action
action().positions(Position.footer, Position.row)  // multiple positions
PositionDescription
Position.topPage/section header
Position.footerForm footer
Position.floatingFloating button
Position.rowTable row action

Alignment

By default, actions align to the end. Use .start() to align left:

typescript
action().start()   // align to start
action().end()     // align to end (default)

Ordering

Control the display order of actions:

typescript
action().order(1)     // lower numbers appear first
action().order(999)   // higher numbers appear later
action().order(-1)    // negative numbers appear before 0

Icons

Attach an icon to an action:

typescript
import { Icon } from '@anhanga/core'

action().icon(Icon.Save)
action().icon(Icon.Trash)
action().icon(Icon.Send)

Scoping

Control which scopes display an action:

typescript
action().scopes(Scope.add)                       // only in add scope
action().scopes(Scope.add, Scope.edit)            // add and edit
action().excludeScopes(Scope.add, Scope.view)     // everywhere except add and view

See Scopes for details.

Hiding Actions

Use .hidden() to keep an action in the configuration but hide it from the UI:

typescript
action().hidden()  // hidden but still inheritable

Removing Inherited Actions

Set an action to null to remove it from the inherited base schema:

typescript
const PersonSchema = schema.create('person', {
  actions: {
    destroy: null,  // removes the inherited destroy action
  },
})

Action Handlers

Handlers define what happens when an action is triggered:

typescript
const personHandlers = PersonSchema.handlers({
  create({ state, component, form }) {
    if (!form?.validate()) return
    service.create(state)
    component.toast.success('Created!')
    component.navigator.push(component.scopes[Scope.index].path)
  },
  cancel({ component }) {
    component.navigator.back()
  },
  destroy({ state, component }) {
    service.destroy(state.id)
    component.toast.success('Deleted!')
    component.navigator.push(component.scopes[Scope.index].path)
  },
})

The handler context provides:

PropertyTypeDescription
stateRecord<string, unknown>Current form state
componentComponentContractNavigator, toast, dialog, loading
formFormContractValidate, reset, errors, dirty
tableTableContractTable state (when in index scope)

Released under the MIT License.