Skip to main content
Properties carry enough metadata to render themselves in any context. The same property definition that drives validation also drives how a value appears in a detail page, an edit form, a data table column, or an inline edit popover — with no extra configuration. There are four rendering surfaces:
SurfaceComponent / APIContext
Read-only display<PropertyValue>Detail pages, activity logs
Inline edit<PropertyValue action={...}>Detail pages, tables
Form input<PropertyCoreFormInput>Create / edit forms
Table columnPropertyColumn::fromSchema()Data tables
Table filterPropertyFilter::fromSchema()Data table filter bar

Displaying a Value

<PropertyValue> renders the read-only display component for a property type. Pass the serialized property from the backend — it contains the type, value, formatted value, and label all in one object.
import { PropertyValue } from '@/core/properties';

<PropertyValue data={properties.status} />
<PropertyValue data={properties.total_amount} />
Pass the schema data from the controller:
return CoreShowPage::make('orders/order-show')
    ->fromDomainObject($order)
    ->with([
        'properties' => $order->properties()->toData(),
    ]);
Or pass individual properties:
->with([
    'statusProperty' => $order->property('status'),
    'totalProperty'  => $order->property('total_amount'),
])

Inline Edit

Pass an action to <PropertyValue> to make a value inline-editable. The display wraps in a hover target — clicking it opens a popover with the property’s input component pre-filled.
<PropertyValue data={properties.status} action={updateStatusAction} />
Pass the action from the controller alongside the property data:
->with([
    'statusProperty'      => $order->property('status'),
    'updateStatusAction'  => UpdateOrderStatusAction::make()->params(['id' => $order->id]),
])
The property name is used as the default parameter name for the mutation. Override it with paramName if your action expects a different key.
Image and file properties are always read-only — the inline edit affordance does not appear even if an action is provided.
For full control, use <PropertyInlineEdit> to wrap arbitrary content:
import { PropertyInlineEdit } from '@/core/properties';

<PropertyInlineEdit property={property} action={updateAction}>
  <CustomDisplay />
</PropertyInlineEdit>;

Form Input

<PropertyCoreFormInput> resolves the correct form input for a property type and places it inside a CoreActionForm or CoreForm. Label, description, and validation state are derived from the property data automatically.
import { PropertyCoreFormInput } from '@/core/properties';

<CoreActionForm action={updateAction} form={form} footer={...}>
  <PropertyCoreFormInput data={properties.status} />
  <PropertyCoreFormInput data={properties.ordered_at} />
  <PropertyCoreFormInput data={properties.notes} />
</CoreActionForm>
Each property type maps to a specific CoreForm component:
Property typeRenders
stringCoreFormInput
numberCoreFormInput
moneyCoreFormMoneyInput
booleanCoreFormSwitch
dateCoreFormInput
enumCoreFormSelect
textCoreFormTextarea
objectCoreFormSearchCombobox

Overriding Defaults

Override the name, label, or description derived from property metadata:
<PropertyCoreFormInput
  data={property}
  name="custom_field"
  label={__('Custom Label')}
/>
Pass an empty string to suppress the label:
<PropertyCoreFormInput data={property} label="" />

Passing Props to the Underlying Input

Use inputProps to forward props to the underlying CoreForm component. For string and number properties this supports prefix, suffix, iconLeft, iconRight, and transformValue:
<div className="flex gap-2">
  <PropertyCoreFormInput
    data={schema.map_position_x}
    label=""
    inputProps={{ prefix: 'X' }}
  />
  <PropertyCoreFormInput
    data={schema.map_position_y}
    label=""
    inputProps={{ prefix: 'Y' }}
  />
</div>
Use PropertyCoreFormInput when the backend provides property metadata via schemas. For forms where you know the field types at build time, use the specific field components from the Forms reference directly.

Table Columns

PropertyColumn::fromSchema() creates a table column from a schema property. It automatically:
  • Uses the property’s label
  • Renders the cell with <PropertyValue>
  • Marks direct-column and aggregate properties as sortable
  • Maps toFormatted() to the export value
app/Tables/OrderTable.php
use Inly\Core\Properties\Adapters\InertiaTable\PropertyColumn;

public function columns(): array
{
    return [
        PropertyColumn::fromSchema(Order::class, 'order_number'),
        PropertyColumn::fromSchema(Order::class, 'customer_name'),
        PropertyColumn::fromSchema(Order::class, 'status'),
        PropertyColumn::fromSchema(Order::class, 'total_amount'),
        ActionColumn::new(),
    ];
}
Always apply the schema to the query so relation and aggregate data is available:
public function resource(): Builder|string
{
    return Order::query()->applyToQuery();
}

Inline Edit in Tables

Add ->editable() to enable inline editing directly in the table cell:
PropertyColumn::fromSchema(Order::class, 'status')
    ->editable(
        actionClass: UpdateOrderStatusAction::class,
        params: fn ($record) => ['id' => $record->id],
    ),
Override paramName if the action expects a different parameter name than the property name:
PropertyColumn::fromSchema(Order::class, 'status')
    ->editable(
        actionClass: UpdateOrderStatusAction::class,
        params: fn ($record) => ['id' => $record->id],
        paramName: 'order_status',
    ),

Standalone Columns

Use PropertyColumn::make() with a property instance when you don’t have a schema — for ad-hoc columns:
use Inly\Core\Properties\Types\StringProperty;

PropertyColumn::make(StringProperty::make('notes', __('Notes'))),
Standalone columns don’t auto-derive sortability or export formatting. Chain these manually as needed.

Table Filters

PropertyFilter::fromSchema() picks the right filter type based on the property’s semantic metadata:
Property characteristicFilter type
Has options()CoreSetFilter (checkbox list)
Type booleanToggle filter
Type dateDate range filter
Type number / moneyNumeric range filter
Everything elseText filter
app/Tables/OrderTable.php
use Inly\Core\Properties\Adapters\InertiaTable\PropertyFilter;

public function filters(): array
{
    return [
        PropertyFilter::fromSchema(Order::class, 'status'),    // → CoreSetFilter (OrderStatus options)
        PropertyFilter::fromSchema(Order::class, 'ordered_at'), // → CoreDateFilter
    ];
}

Reference

PropertyColumn

MethodDescription
make(Property $property): staticStandalone column from a property instance
fromSchema(string $schemaClass, string $propertyName): staticSchema-bound column with auto-derived sortability and export
editable(string $actionClass, ?Closure $params, ?string $paramName = null): staticEnable inline edit via action

PropertyFilter

MethodDescription
make(Property $property): mixedStandalone filter from a property instance
fromSchema(string $schemaClass, string $propertyName): mixedSchema-bound filter; auto-selects filter type

Next Steps

Properties

Define property types, constraints, computed values, and validation rules.

Data Tables

Use PropertyColumn and PropertyFilter to build schema-driven tables.