Member Junction
    Preparing search index...

    Wraps a Component (the IC kind — declared componentRole: 'form') so it can stand in for an Angular form on any entity.

    Layering invariant: the React component never touches BaseEntity. This wrapper owns the entity lifecycle (record.Save, record.Delete, mode transitions). The React component sees only the snapshot in FormHostProps and communicates back via BeforeSave / BeforeDelete / EditModeChangeRequested events plus its dirty-field diff.

    Instantiated by SingleRecordComponent.LoadForm when the resolver finds an EntityFormOverride matching the user's scope. Behaves exactly like the generated Angular form from the host's perspective: same record setter, same EditMode toggle, same outputs.

    Hierarchy (View Summary)

    Implements

    • OnInit
    • OnDestroy
    Index

    Constructors

    Properties

    Accessors

    Methods

    BuildOrganicKeyViewParams BuildOrganicKeyViewParamsByNames BuildRelationshipViewParams BuildRelationshipViewParamsByEntityName BuildRelationshipViewParamsForJoinFields CancelEdit CheckDuplicateEntry CheckUserPermission collapseAllSections ConfigureToolbarItem DisableToolbarItem DismissDuplicateNotice EnableToolbarItem EndEditMode expandAllSections FormatField FormatValue getDefaultFormWidthMode getEntityName GetEntityRelationshipByRelatedEntityName getExpandedCount getFirstClassSectionKeys getFormWidthMode GetListsCanAddTo getMoreSectionKeys GetRecordDependencies GetRelatedEntityTabDisplayName getSection getSectionDisplayOrder getSectionOrder getSectionOrderIndex GetSectionPanelHeight GetSectionRowCount getTotalSectionCount getVisibleSectionCount GridEditMode handleHistoryDialog HandleTagsPanel hasCustomSectionOrder HideToolbarItem initSections InternalSaveRecord IsSectionExpanded MakeFavorite NewRecordValues NewRecordValuesByEntityRelationship NewRecordValuesForJoinFields ngAfterViewInit ngOnDestroy ngOnInit OnCustomToolbarButtonClick OnDeleteRequested OnFavoriteToggled OnFieldEdited onFilterChange OnFormNavigate OnHistoryRequested OnListManagementRequested OnOpenEntityRecord OnReactComponentEvent OpenDuplicateCandidate PeekSectionRowCount PendingRecordsDirty PopulatePendingRecords RaiseEvent RefreshRecord RegisterFormPanel RegisterToolbarItem RemoveFavorite resetSectionOrder SaveRecord setChromeMembership SetFavoriteStatus setFormWidthMode SetSectionBadgeVisible SetSectionExpanded setSectionOrder SetSectionPanelHeight SetSectionRowCount SetToolbarItemOrder ShowChanges ShowDependencies ShowToolbarItem splitterLayoutChange StartEditMode toggleFormWidthMode toggleSection UnregisterFormPanel UnregisterToolbarItem Validate ValidateAsync ValidatePendingRecords Wait

    Constructors

    Properties

    BottomAreaSize: number = 60

    Size of the bottom area as a percentage (0-100) for angular-split. Used by CodeGen-generated templates with as-split.

    cdr: ChangeDetectorRef = ...
    ChromeLayout: "accordion" | "left-nav" = 'accordion'

    Layout the container resolved for this form. Set by <mj-record-form-container>; read by panel hosts.

    collapsiblePanels: QueryList<MjCollapsiblePanelComponent>
    ComponentID: string | null = null

    The Component row ID resolved for this (entity, user, roles) tuple. Set by SingleRecordComponent.LoadForm after the resolver returns an override.

    componentSpec: ComponentSpec | null = null

    Loaded ComponentSpec, parsed from the Component row's Specification JSON.

    Two ways to populate this:

    1. Via ComponentID (the standard path): set the input, ngOnInit fetches the row from MJ: Components and assigns the parsed spec.
    2. Direct assignment (the artifact-viewer path): the caller already has the spec in hand (parsed from an artifact JSON blob) and sets componentSpec directly. In that case ComponentID should be left null and the DB fetch is skipped.
    CompositionChanged: EventEmitter<FormCompositionSnapshot> = ...
    CompositionSnapshot: FormCompositionSnapshot | null = null

    Last composition snapshot the container published — what is actually on this form: sections, related grids, contributions and slots. Consumers: agent context (so Skip can target a real slot and section key) and Form Studio.

    Config: EntityFormConfig | null = null

    Per-instance presentation config (toolbar visibility, related-entity sections, collapsibility, width, in-form navigation). Set by the form host (MjEntityFormHostComponent) or any consumer that instantiates the form directly. Read back by MjRecordFormContainerComponent and the collapsible panels through the FormComponent reference, so it takes effect WITHOUT regenerating the CodeGen-produced template. Null means "use the container's own defaults" (the classic full-page tab behavior).

    CurrentVariantID: string | null = null

    ID of the currently-rendered variant (null when no override is active and the form is the CodeGen /

    default).

    EditMode: boolean = false
    EditModeChanged: EventEmitter<boolean> = ...

    Emitted whenever edit mode starts (true) or ends (false). The Explorer shell uses the true edge to PROMOTE a records preview tab — pin it — the moment the user starts editing (VS Code's promote-on-modify), so a record being edited is neither replaceable by the next plain open nor italic. Fires on every call, not only on transitions: a new record's ngOnInit re-asserts edit mode and the shell's pin is idempotent.

    elementRef: ElementRef<any> = ...
    FavoriteInitDone: boolean = false
    FormHostProps: FormHostProps | null = null

    FormHostProps passed to the React component. Recomputed when record or mode changes.

    formStateService: FormStateService = ...
    isHistoryDialogOpen: boolean = false
    IsRefreshing: boolean = false
    IsTagsPanelOpen: boolean = false
    LoadErrorChanged: EventEmitter<string | null> = ...
    Navigate: EventEmitter<FormNavigationEvent> = ...

    Emitted when navigation is requested (record link, external link, email, new record, etc.)

    Notification: EventEmitter<FormNotificationEvent> = ...

    Emitted when a user-facing notification should be shown

    OnVariantChanged: (variantID: string | null) => void = ...

    Hook called when the user picks a different variant from the picker. Default is a no-op; the Explorer-level single-record component replaces this on the form instance to wire FormResolverService.SetSelectedVariant and reload the record. Kept as a method (not an EventEmitter) so the host doesn't need to subscribe — assignment is enough.

    placementPreview: FormPlacementPreview | null = ...

    The placement dialog's unsaved panel, when this form is the dialog's preview.

    PreviewMode: boolean = false

    When true, render the React component without the <mj-record-form-container> wrapper — i.e. no toolbar (no Save / Cancel / Edit / Delete / History / Tags / Lists).

    Used by the Form Builder cockpit's Preview tab where the toolbar's actions don't apply (Save would save the record, but the cockpit's own Save button saves the spec; History/Tags assume a real persistent record, but the preview record can be a synthetic NewRecord). Keeping just the form body produces a clean "this is what the form looks like" view.

    Provider: IMetadataProvider | null

    If specified, this provider will be used for communication and for all metadata purposes. By default, if not provided, the Metadata and RunView classes are used for this and the default GraphQLDataProvider is used which is connected to the same back-end MJAPI instance as the Metadata and RunView classes. If you want to have this component connect to a different MJAPI back-end, create an instance of a ProviderBase sub-class like GraphQLDataProvider/etc, and configure it as appropriate to connect to the MJAPI back-end you want to use, and then pass it in here.

    ReactComponent?: MJReactComponent

    Reference to the mounted React component. Used by the SaveRecord / CancelEdit overrides below to invoke the component's registered RequestSave / RequestCancel methods when the host toolbar fires Save/Cancel — so the single user-visible Save lives on the toolbar (consistent with every other entity form in MJ) and not duplicated inside the form body.

    RecordDeleted: EventEmitter<RecordDeletedEvent> = ...

    Emitted after a record is deleted successfully

    RecordDeleteFailed: EventEmitter<RecordDeleteFailedEvent> = ...

    Emitted when a record delete fails

    RecordReady: EventEmitter<BaseEntity<unknown>> = ...

    Emitted once after ngOnInit completes and the record is fully initialized (favorites loaded, form state initialized). This is the safe point for the container to start loading badge counts and other record-dependent data.

    RecordRefreshed: EventEmitter<RecordRefreshedEvent> = ...

    Emitted after a record is refreshed from the database successfully

    RecordSaved: EventEmitter<RecordSavedEvent> = ...

    Emitted after a record is saved successfully

    RecordSaveFailed: EventEmitter<RecordSaveFailedEvent> = ...

    Emitted when a record save fails

    searchFilter: string = ''
    SectionRowCountChanged: EventEmitter<
        { Previous: number
        | undefined; RowCount: number; SectionKey: string },
    > = ...

    Fires when a section's known row count changes — from the container's batched count prefetch, a related grid load (including a manual grid refresh), or a contribution reporting its own count. The container re-resolves empty-section chrome (whenEmpty) when a count crosses zero.

    sections: BaseFormSectionInfo<any>[] = []
    showCreateDialog: boolean = false
    showDeleteDialog: boolean = false
    showEmptyFields: boolean = false
    TagCount: number = 0
    TopAreaHeight: string = '300px'

    Height of the top area when a splitter layout is used. Referenced by CodeGen-generated templates for entities with "top area" sections.

    TopAreaSize: number = 40

    Size of the top area as a percentage (0-100) for angular-split. Used by CodeGen-generated templates with as-split.

    ValidationFailed: EventEmitter<ValidationFailedEvent> = ...

    Emitted when validation fails before save

    Variants: {
        ID: string;
        Label: string;
        Scope: "User" | "Role" | "Global";
        Status: "Active" | "Pending" | "Inactive";
    }[] = []

    Variants applicable to the current (entity, user) tuple, supplied by the Explorer-level form resolver. When more than one entry is present, the record-form-container shows a picker that lets the user switch between variants. Empty / single-entry arrays hide the picker.

    The container reads this via its EffectiveVariants accessor — generated form templates do NOT need to bind it explicitly.

    "ɵdir": unknown
    "ɵfac": ɵɵFactoryDeclaration<BaseAngularComponent, never>

    Accessors

    • get formContext(): FormContext

      Context handed to every field, panel and slot in the form.

      Returns the SAME object while nothing in it has changed. Templates bind this getter in dozens of places per form, and Angular evaluates each binding on every change-detection pass — so allocating a fresh object per access handed every child a new reference each pass, defeating input-identity checks and cascading re-renders through the whole form. Building the candidate is cheap (the expensive part, hidden section keys, is memoized); the identity comparison below is what stops the cascade.

      Returns FormContext

    • get HasAdditionalUnsavedChanges(): boolean

      Unsaved changes a form holds OUTSIDE its record's fields and pending records.

      A form whose sections own editors — a flow canvas, a designer, a grid — accumulates edits that neither record.Dirty nor PendingRecordsDirty() can see, because nothing on the entity changed. Without this the toolbar reports "no changes" while the user is looking at their own work, and the navigate-away guard lets them lose it silently.

      Default false, so no existing form changes behaviour. Override to consult whatever holds the extra state.

      Returns boolean

    • get ProviderToUse(): IMetadataProvider

      Returns either the default Metadata provider or the one specified in the Provider property, if it was specified

      Returns IMetadataProvider

    • get RunQueryToUse(): IRunQueryProvider

      Returns either the default RunQuery provider or the one specified in the Provider property, if it was specified

      Returns IRunQueryProvider

    • get RunViewToUse(): IRunViewProvider

      Returns either the default RunView provider or the one specified in the Provider property, if it was specified

      Returns IRunViewProvider

    Methods

    • Toolbar Cancel override. Asks the React component to discard its draft via RequestCancel, then flips out of edit mode the same way the base implementation would. The React component is expected to (a) clear its local draft state and (b) emit EditModeChangeRequested({ requestedMode: 'view' }) — though we call EndEditMode here directly anyway, so even a no-op handler leaves the form in a coherent state.

      Returns void

    • Component-level default width mode, used when the user has NOT explicitly chosen a width for this entity yet (first visit, nothing persisted in User Settings). Subclasses can override this — for example, custom forms with full-bleed layouts should return 'full-width' here and the container will respect it on first open.

      Once the user toggles the width via the toolbar, their choice persists via setFormWidthMode() and takes priority over this default on subsequent opens.

      Returns "centered" | "full-width"

    • Where this key sits in the section order, or null when it is not in it at all.

      getSectionDisplayOrder cannot answer that: it returns the section count for an unknown key, which is indistinguishable from a real last position. A contribution panel is not in the form's declared sections, so a caller has to be able to tell "the user placed this here" from "nobody has said where this goes".

      Parameters

      • sectionKey: string

      Returns number | null

    • Parameters

      • sections: (
            | BaseFormSectionInfo<any>
            | {
                isExpanded: boolean;
                metadata?: unknown;
                rowCount?: number;
                sectionKey: string;
                sectionName: string;
            }
        )[]

      Returns void

    • Default values for a new related-entity record so it links back here. Pass relatedEntityJoinField when more than one relationship targets the same entity (Bill-To vs Ship-To). When omitted and several matches exist, every matching FK is set — same fields the related grid is filtering on.

      Parameters

      • relatedEntityName: string
      • OptionalrelatedEntityJoinField: string

      Returns Record<string, unknown>

    • A person edited a field on this form. For a new record this restarts the entry-time duplicate check. mj-record-form-container calls it for every mj-form-field edit; a custom editor that changes the record some other way can call it too.

      A user who cannot read the entity (one who may only create its records) never starts a check: the server would refuse it, and a flagged record is one they could not open anyway.

      Returns void

    • Toolbar Save override. Routes the click through the React component's registered RequestSave method so the React layer can (a) run its own validation, (b) flush its draft state, (c) emit BeforeSave with the dirty-field diff — exactly the flow the in-form Save button would trigger. The wrapper then awaits the BeforeSave handler via pendingSaveResolver, gets a real success/failure boolean, and honors StopEditModeAfterSave.

      Falls back to the base implementation for components that haven't registered RequestSave — preserves correctness for forms that keep their own in-form Save button (older sample, hand-authored forms that pre-date this contract).

      Parameters

      • StopEditModeAfterSave: boolean

      Returns Promise<boolean>

    • Validate, merged with every mounted panel's validator, awaited. This is what SaveRecord() calls.

      It starts from Validate(), so a subclass that overrides Validate() still gates the save; the panels' last-known state is left out of that call, because their awaited results replace it.

      A panel's Validate() may be async — anything checking server state will be — and reading such a result synchronously yields a Promise, which tests as "no opinion" and lets an invalid record save with no error and no log.

      Returns Promise<ValidationResult>