ObjectUIObjectUI
Fields

User Field

User and owner selector with avatar display

The User Field component provides a user selector for assigning users or owners to records. It displays user avatars and supports both single and multiple user selection.

Basic Usage

Single User Selection

Multiple Users

Multiple User Selection

Read-Only Record Owner

A record-owner field is a plain user field whose NAME carries the ownership meaning — there is no separate owner type. Marking it readonly is what makes it display-only.

Record Owner Read Only

Field Schema

A user field is authored as UserFieldMetadata (@object-ui/types), which is the source of truth for the key set: it extends BaseFieldMetadata with the picker style, the subtitle fields, the avatar field and the candidate filters. user is a lookup specialised to the sys_user system object, so its filters are LookupFilterDef.

import type { UserFieldMetadata } from '@object-ui/types';

const owner: UserFieldMetadata = {
  type: 'user',
  name: 'owner_id',
  label: 'Owner',
  required: true,
  multiple: false,
  picker: 'search',
  subtitle: ['primary_business_unit_id.name', 'email'],
  avatar_field: 'image',
  lookupFilters: [{ field: 'banned', operator: 'ne', value: true }],
};

The field stores the selected user's id (or an array of ids when multiple is set), not a user object; the picker resolves names and avatars from sys_user itself.

The value being edited, and the className / disabled a host supplies, are not metadata keys — they are runtime widget props. See Field Widget Props.

User vs Owner

Both are the same field type. What differs is the field's name and whether it is writable:

  • Assignment field: a selectable user field for assignees, team members, etc.
  • Owner field: a user field named owner, typically readonly and defaulted to the record creator.

There is no owner field type. It existed as a synonym until objectui#4814 retired it (it resolved to the very same widget, and it was never a member of @objectstack/spec's FieldType). Authoring type: 'owner' now renders a visible refusal naming this migration rather than silently falling back to a text input. Write { type: 'user', name: 'owner' } instead.

Display Features

  • Avatar Badges: User avatars with initials if no image
  • Color Coding: Consistent colors for user avatars
  • Multiple Display: Shows up to 3 users, then "+N more"
  • Hover Info: User details on avatar hover

Cell Renderer

In tables/grids, displays avatar with name:

import { UserCellRenderer } from '@object-ui/fields';

// Single user: Avatar + name
// Multiple users: Overlapping avatars + count

How it works

user fields are a lookup specialized to the framework's sys_user object — there is no custom user API to wire up. The UserField widget delegates to the shared lookup picker with the reference fixed to sys_user, reusing the same debounced search, record-picker dialog and id resolution as any lookup field:

  • The field stores the selected user's id (a foreign key to sys_user); multiple: true stores an array of ids.
  • A dataSource (provided by SchemaRenderer / the app shell) supplies the candidate search — the picker queries sys_user by name/email as you type.
  • On read, $expand resolves the id(s) to the full user record so cells and read-only views show the name/avatar (via UserCellRenderer).

No custom user-management integration is required when a dataSource is present.

Permission Patterns

Common permission configurations:

// Record owner only — a `user` field whose NAME carries the ownership meaning
{
  type: 'user',
  name: 'owner',
  label: 'Owner',
  readonly: true,
  defaultValue: 'current_user'
}

// Assignable user
{
  type: 'user',
  name: 'assigned_to',
  label: 'Assigned To',
  required: true
}

// Team members
{
  type: 'user',
  name: 'collaborators',
  label: 'Collaborators',
  multiple: true
}

Use Cases

  • Task Management: Task assignee, reviewer
  • CRM: Account owner, opportunity owner
  • Support: Ticket assignee, support agent
  • Project Management: Project members, task owners
  • Approval Workflows: Approvers, reviewers
  • Collaboration: Document collaborators, editors

Backend behavior

The platform handles the common cases natively — you generally don't write backend code for user fields:

  • Owner stamping — declare defaultValue: 'current_user' and the acting user's id is filled in at insert time (no create hook required).
  • Display resolution — request expand=<field> and the stored id(s) resolve to the full sys_user record (name / avatar) for rendering.
  • Ownership & permissions — record ownership and row-level security continue to use the platform's owner_id convention and security rules.

On this page