Skip to content

RecordFieldInspector

<caos-record-field-inspector>

one record as a flat, sortable, in-place editable list of all its fields

May be placed on a page inside an app and a record page.

Name Attribute Description Type Default Required
fields property only Every field of the record: { apiName, label, type, value?, lock? }[]. lock is why a field cannot be edited — computed, no-permission or masked — and each reads as its own sentence in the row, because those three need different things from the reader. json empty list Optional
recordId record-id, markup only Which record this is. Changing it CLEARS the pending edits — carrying them across would write one record’s half-finished changes onto another. recordId none declared Optional
search search, markup only Narrows the rows by API name, label or type. Reflected, so it can be linked to. text none declared Optional
saving saving, markup only A save is in flight: Save reads “Saving…” and every action is held. boolean false Optional
deletable deletable, markup only Show the delete control. Absent ⇒ hidden rather than disabled: a control for something this person cannot do is a question they should not have to ask. boolean false Optional
sortKey sort-key, markup only Which of the four columns the rows are ordered by. All four matter: looking for a field by API name, by label, by type, and looking for which ones have values in them are four different searches, and a fixed order serves at most one. text — one of apiName, label, type, value apiName Optional
sortDirection sort-direction, markup only Which way. Empty values sort last in both directions. text — one of asc, desc asc Optional
Name When it fires What it carries
caos-field-edit A value is typed into. Fires for each change, including one that returns a field to its original. { apiName, value, dirty }.
caos-record-save Save is pressed. Never while saving, and never with nothing changed. { recordId, changes } — changes holds ONLY the fields that changed. A component handing back every field it was given would make every save a full overwrite.
caos-record-discard Discard is pressed with changes pending. nothing
caos-record-export Export is pressed. { recordId, fields } — the fields as currently filtered and ordered.
caos-record-delete The delete control is pressed. { recordId }. It ASKS: whether a record can be deleted, and what warning that deserves, is not a component’s call, and an irreversible act behind an unconfirmed click is not one either.

Not documented yet — this piece has not said.

Not documented yet — this piece has not said.

Name Description Arguments
accept() Clear the pending edits. What a host calls once a save has actually landed — the component does not assume its own event succeeded. takes none
Name Type What it tells you
pending { [apiName]: string } The changed fields and their new values. Empty when nothing is pending.
dirty boolean Whether anything is pending. A comparison against the values handed in, not a flag somebody sets — so typing a value and typing the original back leaves it false.
visibleFields CaosRecordField[] The fields after the search, in the current order.
Part Which piece of it When it is there
::part(inspector) The outer column. Always
::part(toolbar) The search and action row. Always
::part(search) The search box. Always
::part(actions) The save / discard / export / delete cluster. Always
::part(summary) The field count and unsaved-change line. Always
::part(table) The composed data table. Always
::part(value-input) The editor in one value cell. The field is not locked.
::part(reason) The text in a locked field’s value cell. The field is locked.

When somebody needs the WHOLE record — API names included — rather than the fields a layout chose to show. Debugging, data fixing, and answering “is that field even populated”.

  • FieldRenderer — the fields are being presented to a person doing their job, where the layout, the labels and the typed controls are the point. This is the developer’s flat view of the same record.
  • KeyValueRow — a handful of named values are being read and nothing is being edited.

Every value editor carries an accessible name reading the label and the API name, so a row read aloud says which field is being edited rather than announcing an unlabelled text box. The summary is a role="status" live region, so the number of unsaved changes is announced as it moves — somebody editing down a long list is not looking at the header. A locked field shows the reason as text in its own cell rather than as a disabled control, because “you cannot” is the half a reader already worked out and “the platform computes it” is the half they need.

The flat view: API name, label, type and value, with one field edited and not yet saved. Save and Discard are both enabled, and the summary counts the change.

{
"id": "example",
"section": "A record with a change pending",
"columns": 1,
"items": [
{
"id": "record_field_inspector_1",
"type": "component",
"key": "record_field_inspector",
"inputs": {
"record_id": "001x00000A1b2C",
"deletable": true,
"fields": [
{
"apiName": "Id",
"label": "Record Id",
"type": "Id",
"value": "001x00000A1b2C",
"lock": "computed"
},
{
"apiName": "Name",
"label": "Account Name",
"type": "Text",
"value": "Northwind Traders"
},
{
"apiName": "Industry",
"label": "Industry",
"type": "Picklist",
"value": "Retail"
},
{
"apiName": "AnnualRevenue",
"label": "Annual Revenue",
"type": "Currency",
"value": 4200000
},
{
"apiName": "Website",
"label": "Website",
"type": "Url",
"value": null
},
{
"apiName": "CreatedDate",
"label": "Created Date",
"type": "DateTime",
"value": "2025-03-04T09:11:00Z",
"lock": "computed"
}
]
}
}
]
}
<caos-record-field-inspector id="recordFieldInspector1" record-id="001x00000A1b2C" deletable></caos-record-field-inspector>
// What an attribute cannot hold, set as a property — the same values the preview is drawn with.
const recordFieldInspector1 = document.getElementById('recordFieldInspector1');
recordFieldInspector1.fields = [
{
"apiName": "Id",
"label": "Record Id",
"type": "Id",
"value": "001x00000A1b2C",
"lock": "computed"
},
{
"apiName": "Name",
"label": "Account Name",
"type": "Text",
"value": "Northwind Traders"
},
{
"apiName": "Industry",
"label": "Industry",
"type": "Picklist",
"value": "Retail"
},
{
"apiName": "AnnualRevenue",
"label": "Annual Revenue",
"type": "Currency",
"value": 4200000
},
{
"apiName": "Website",
"label": "Website",
"type": "Url",
"value": null
},
{
"apiName": "CreatedDate",
"label": "Created Date",
"type": "DateTime",
"value": "2025-03-04T09:11:00Z",
"lock": "computed"
}
];

The three reasons a field cannot be edited

Section titled “The three reasons a field cannot be edited”

Computed by the platform, not permitted to this person, and masked. Each says which, because they need different things from the reader and a greyed box says none of it.

{
"id": "example",
"section": "The three reasons a field cannot be edited",
"columns": 1,
"items": [
{
"id": "record_field_inspector_1",
"type": "component",
"key": "record_field_inspector",
"inputs": {
"record_id": "001x00000A1b2C",
"fields": [
{
"apiName": "Name",
"label": "Account Name",
"type": "Text",
"value": "Northwind Traders"
},
{
"apiName": "LastModifiedDate",
"label": "Last Modified",
"type": "DateTime",
"value": "2026-09-02T14:00:00Z",
"lock": "computed"
},
{
"apiName": "CreditRating__c",
"label": "Credit Rating",
"type": "Text",
"value": "A-",
"lock": "no-permission"
},
{
"apiName": "TaxId__c",
"label": "Tax Id",
"type": "Text",
"value": "99-1234567",
"lock": "masked"
}
]
}
}
]
}
<caos-record-field-inspector id="recordFieldInspector1" record-id="001x00000A1b2C"></caos-record-field-inspector>
// What an attribute cannot hold, set as a property — the same values the preview is drawn with.
const recordFieldInspector1 = document.getElementById('recordFieldInspector1');
recordFieldInspector1.fields = [
{
"apiName": "Name",
"label": "Account Name",
"type": "Text",
"value": "Northwind Traders"
},
{
"apiName": "LastModifiedDate",
"label": "Last Modified",
"type": "DateTime",
"value": "2026-09-02T14:00:00Z",
"lock": "computed"
},
{
"apiName": "CreditRating__c",
"label": "Credit Rating",
"type": "Text",
"value": "A-",
"lock": "no-permission"
},
{
"apiName": "TaxId__c",
"label": "Tax Id",
"type": "Text",
"value": "99-1234567",
"lock": "masked"
}
];