Related Form Component
Lets the operator edit mediatype records that are related to the page's main mediatype — displayed as one form per related record rather than as a list. Use it when each related record has many fields the operator needs to see at once (audio tracks with codec / bitrate / language / file ref; pricing offers with start / end / amount / currency). Use the Simple Related List when many records with few columns each fits the UX better, or the Related Auto Complete when only the related record's identity matters.

The example above is from a user edit page where a Related Form
component holds the user's "video service info" record — a single
related record with many fields (Geographic Area, Blackout Area,
Time Zone, DVR, SD Media Streams, HD Media Streams, DVBT Tuners,
Service Group, …). With CREATE_ONLY_ONE_RELATED_REGISTRY
the component enforces a single child record and hides the
Add Related / Delete affordances.
Related Form is distinct from Related List. They share neither the React widget nor the schema shape on the wire. This doc covers Related Form only — see Related List for that component and for the Header Action / Item Action extension points (those features live on the Related List widget, not here).
Related docs.
Form Component — the parent on the same page; shares the field-rendering pipeline.
Simple Related List — list-style alternative for the same relationship.
Related Auto Complete — minimal alternative when only the related record's identity matters.
System Overview — RenderV2 — the request that returns{schema, data}to the React shell.
Choosing between the four "Related" components
The four components below are interchangeable from the data-model side — they all describe the same relationship between the page's mediatype and another. Pick by the UX you want:
| Component | When to use |
|---|---|
| Simple Related List | Many records, few columns. Table view. |
| Ordered Related List | Same as above, with drag-and-drop reordering. ≤15 rows. |
| Related Form (this doc) | Few records, many fields each. Form-per-record view. |
| Related Auto Complete | Only the related record's identity matters. Autocomplete-style picker. |
Backend features (C# — MibServer3)
The C# class is MediaiBox.Cms.FrontEnd.Server.Component.RelatedFormComponent,
with its typed configuration at RelatedFormComponentConfiguration and
its view data at
MediaiBox.Cms.FrontEnd.Model.UI.Form.RelatedFormViewData. The
component:
- Loads the related records into a
List<RelatedChildFormViewData>at render time. - Honours the parent form's permissions (you only see records the user has read on the related mediatype).
- Drives the same field-render pipeline as the main Form Component —
every
admFieldvariant supported by Form is supported here.
Bulk modes — PersistenceBulkMode
When the parent page is in bulk-edit (the user arrived from a list
with multiple ids), Related Form supports four explicit operation
modes via the PersistenceBulkMode enum
(MediaiBox.Cms.FrontEnd.Model.Dao.Persistence.PersistenceBulkMode):
| Mode | Effect on each selected parent record |
|---|---|
None |
Default — apply field changes as edited. |
Add |
Append the related record to each parent's relation set. |
Remove |
Remove the related record from each parent's relation set. |
Clear |
Clear all related records on each parent. |
Replace |
Replace the existing relation set with the edited one. |
The mode is selected at save time via a JSON option sent by the
client: data.Options = { type: "bulk", mode: "..." }. If the
operator triggers a bulk save but the component has AllowBulkEdit = false, the C# layer throws BulkEditDeniedException and the save is
rejected with a clear error.
This is one of the highest-value backend features for the Related Form — it lets editors mutate hundreds of parents in a single save without the client having to issue N independent updates.
Remove-button behaviour — RemoveButtonBehaviorType
What clicking the per-record trash button actually does depends
on the relation type and the RemoveButtonBehaviorType set on the
view data:
| Behaviour | Meaning |
|---|---|
SetNull (default for nullable foreign-key relations) |
Set the foreign key to null on the parent; do not delete the child record itself. |
DontAllowRemoval |
The trash button is hidden. Removal isn't possible. |
DeleteChildObject |
Delete the related record from its mediatype entirely. |
SetNull is the safe default for relations that point at shared
catalog records (e.g. a Distributor — un-relating a movie from a
distributor must not delete the distributor). DeleteChildObject is
for owned-child relationships only (e.g. audio tracks that uniquely
belong to one movie).
Copy-with-related — RelatedCopyType
When the parent record is cloned, Related Form's children are copied
according to RelatedCopyType:
| Value | Effect |
|---|---|
Undefined |
Inherit the platform default. |
DoNotCopy |
Skip — the clone has no related records. |
ShallowCopy |
Copy the links — both parents share the same related records. |
DeepCopy |
Duplicate each related record and link the new copies to the clone. |
AllowAddNew interacts with this — see the note on ALLOW_ADD_NEW
below.
Implements
The C# class implements the following framework interfaces:
public class RelatedFormComponent :
ICloneableComponent<RelatedFormComponentConfiguration, RelatedFormViewData>,
IRenderableComponent <RelatedFormComponentConfiguration, RelatedFormViewData>,
IPersistableComponent<RelatedFormComponentConfiguration>,
IRefreshableComponent<RelatedFormComponentConfiguration, RelatedFormViewData>,
ISecondaryRequestComponent
The set of interfaces tells you the supported operations:
- Renderable — emits view data on read.
- Persistable — handles save / delete on its own (including the bulk modes above).
- Refreshable — supports the post-save refresh roundtrip triggered by sibling components changing state.
- Cloneable — participates in copy-with-related when the parent
is cloned (see
RelatedCopyType). - SecondaryRequest — can serve its own AJAX requests outside the normal render flow (used by the legacy MVC pipeline for lazy-loading child forms).
Frontend support (React shell, MibFrontEnd)
Current status: the React shell's core component dispatch
(packages/core-components/src/components/index.ts) maps the
component type relatedform to null — Related Form is not
implemented as a built-in React widget. This means pages that
include a Related Form component currently fall into one of these
buckets:
- Legacy MVC rendering via the
/Display/<pageKey>route — the C# component renders its own Razor view and the page works as it has since pre-React times. Most surviving Related Form usages are here. - A customer-supplied federated remote that registers a
relatedformReact widget — same plug-in pattern any custom component uses (see Component Creation). The customer remote consumes the schema the C# component emits and renders it however the customer chooses.
If you are starting a new component today that needs form-per-record UX, you have two ergonomic options:
- Use the Related Form C# component on a legacy MVC page
(
~/Display/<pageKey>) — works out of the box, no React work. - Use the Simple Related List — list-style but fully supported in the React shell; the operator can click into each row to edit a single record at a time. For cases where the form would have fit in a single horizontal row, this is usually a clean substitute.
If you specifically need a Related-Form React shell experience,
you'll need to ship a custom relatedform widget through your
federated remote. The widget consumes the same { schema, data }
shape the C# RelatedFormViewData emits, so the contract is stable;
only the rendering is your responsibility.
Header Action / Item Action
The shell's Header Action and Item Action decorator pattern
(see Simple Related List — Header Actions and Item
Actions)
is scoped to the 'related-list' decorator namespace and is consumed
by the core React RelatedList widget. It does not apply to
Related Form out of the box because Related Form has no core React
widget.
A custom relatedform widget shipped in a federated remote can
choose to:
- Define its own decorator namespace (e.g.
'related-form') — the cleanest approach if the actions are conceptually form-specific. - Re-use the
'related-list'decorator namespace — if the widget's UX is close enough to the list widget that actions should share the same registration. The Related List section linked above documents the exact contract (props, visibility gating viaschema.configuration[key]for header anddata.items[i].permissions[key]for item).
Either approach is implementer-defined; the framework imposes no constraint here today.
Configuration Keys (C# side)
These are stored in MIB3UX_PAGE_COMPONENT_CONFIGURATIONS and
projected onto RelatedFormComponentConfiguration at render time.
TITLE
The title rendered in the component header.
ALLOW_ADD_EXISTING
Boolean. True (default): the Add Existing action is enabled.
False: hidden.
ALLOW_ADD_NEW
Boolean. True: the Add New action is enabled. False: hidden.
Note
Pairs with RelatedCopyType for the copy-with-relateds flow:
DoNotCopy/ShallowCopy— ifAllowAddNew=trueand the user lacks write permission on the MediaType, related data is not copied.DeepCopy— ifAllowAddNew=falseor the user lacks write permission, related data is not copied.
ALLOW_BULK_EDIT
Boolean. True (default): the page can be bulk-edited (when reached
via multi-select on a list). False: bulk-edit on this component
specifically is disabled. When false and the parent is in
bulk-edit, save throws BulkEditDeniedException.
ALLOW_EDIT
Boolean. True (default): per-record fields are editable. False:
the component is read-only regardless of user permissions.
ALLOW_REMOVE
Boolean. True (default): the per-record trash button is
visible. Its actual behaviour depends on
RemoveButtonBehaviorType.
False: the trash button is hidden regardless of permissions.
ALLOW_CLEAR_ALL
Boolean. True: a "Clear All" button appears in the component
header, removing all related records at once (subject to the same
RemoveButtonBehavior). False (default): the button is hidden.
BATCH_REFERENCE_IDENTIFIER
Sets the batch reference to something other than the component's
default TemplateComponentKey. Used when several components share
a save batch.
CREATE_ONLY_ONE_RELATED_REGISTRY
Boolean. True: the component enforces a single related record
— Add New, Add Existing, and Delete are hidden once one
record is present. False (default): normal multi-record behaviour.
Use for one-to-one relationships modeled as a related table (e.g. a movie's single preview clip).
DENY_ON_READONLY
Boolean. True: deny save if the user lacks permission on any
related component or field on the page. False (default): allow
save even when some related components are read-only for this user.
EXCLUDE_FIELDS
A comma-separated list of admField column names to exclude from
the rendered fields.
CONFIGURATION_KEY: EXCLUDEFIELDS
CONFIGURATION_VALUE: name,timezone,genres
INCLUDE_FIELDS
A comma-separated list of admField column names. When set,
restricts the rendered fields to this list.
CONFIGURATION_KEY: INCLUDE_FIELDS
CONFIGURATION_VALUE: name,timezone,genres
HIDE_BULK_EDIT
Boolean. True: the bulk-edit affordance is disabled even when the
parent page allows it. False (default): enabled.
IS_CHILD_REQUIRED
Boolean. True: at least one related record must exist for the
parent save to succeed. False (default): no requirement.
MEDIATYPE
The mediatype loaded in the component. Required.
PARENT_BATCH_REFERENCE_IDENTIFIER
Override for the parent batch reference (defaults to the parent
component's TemplateComponentKey).
PARENT_MEDIATYPE
Links the parent page's mediatype to the related mediatype rendered here:
CONFIGURATION_KEY: PARENT_MEDIA_TYPE
CONFIGURATION_VALUE: ARTICLES
READONLY
Boolean. True: forces the component read-only regardless of
permissions. False (default): honour user permissions.
READONLY_FIELDS
Comma-separated list of fields rendered as read-only regardless of permissions.
ASIDE_FIELDS / ASIDE_FILTERS
Control the columns and filters shown in the Add Existing side
panel. Same shape as on the Simple Related
List — see that doc
for the value syntax (including dynamic
[templateComponentKey.field] references).
REDIRECT_TO_EDIT_PAGE_BY_FIELD
Dictionary<string, Uri>. Click on a value of the named field in
the rendered form navigates to the edit page of the related
mediatype:
CONFIGURATION_KEY: REDIRECT_TO_EDIT_PAGE_BY_FIELD[ID]
CONFIGURATION_VALUE: react_audio_tracks_edit
Source reference
| React type-key (effective) | relatedList — set via COMPONENT_VIEW_TYPE. The raw class name resolves to relatedform, which is not directly mapped in the React shell's registry today |
| BFF assembly | MibServer3.Web |
| BFF class | MibServer3.Web.Component.RelatedFormComponent |
MIB3UX_COMPONENTS.COMPONENT_KEY |
mib_default_relatedformcomponent |
| React widget source | packages/core-components/src/components/related-list/RelatedList.tsx — the form-per-record variant is driven by schema flags (Aside, RowExpansion); the React side does not have a separate relatedform widget |
| Schema / data contract | Default List Schema plus per-row form schema; see 6.0/React Components |
Custom backend, core React. Emit the Default List shape with the
form-style flags set in the schema's configuration, and set
COMPONENT_VIEW_TYPE = 'relatedList'. The single RelatedList.tsx
widget covers all four related-list variants — see
Simple Related List source reference.
See also
- Form Component — the typical parent component
- Simple Related List — list-style alternative, fully supported in the React shell, including Header Actions and Item Actions
- Ordered Related List — drag-to- reorder variant of Simple Related List
- Related Auto Complete — minimal picker variant
- Component Creation — how to author a
custom React widget for the
relatedformtype if you need it - 6.0/React Components — Default Form Schema — Form-style JSON contract that maps closely to what Related Form emits per child record
- System Overview — RenderV2
— render pipeline that delivers
{schema, data}to the React shell