ElementForm

The ElementForm is a highly versatile component designed to create or update any individual “element” within a quote, such as a vehicle, driver, or insured property. It dynamically renders form fields based on the provided elementModel and can handle complex data dependencies through constraint evaluation, making it a cornerstone of the quoting process.

Usage

To render an ElementForm, you need to provide the specific elementModel that defines its structure, the element object being edited, the overall dataModel, and a timezone. For advanced dependency-driven logic, a dependencyMap and a getEvaluatedConstraints function are also required.

import { ElementForm } from '@socotra/ec-react-components';
import {
    ElementConfig,
    ElementResponse,
    DataModel,
    QuoteDependencyMapResponse,
    EvaluateConstraintsRequest,
    ConstraintEvaluationResponse,
} from '@socotra/ec-react-schemas';

// Example Usage
const MyElementEditor = ({
    elementModel,
    element,
    dataModel,
    dependencyMap,
}: {
    elementModel: ElementConfig,
    element: ElementResponse,
    dataModel: DataModel,
    dependencyMap: QuoteDependencyMapResponse,
}) => {
    const handleSubmit = (elementRequest) => {
        console.log('Element Update Request:', elementRequest);
        // Handle API call to update the element
    };

    const handleEvaluateConstraints = async (
        request: EvaluateConstraintsRequest,
    ): Promise<ConstraintEvaluationResponse | undefined> => {
        console.log('Evaluating constraints for:', request);
        // Replace with your actual API call
        return fetch(/*...- /constraints/evaluate ...*/).then(res => res.json());
    };

    return (
        <ElementForm
            elementModel={elementModel}
            element={element}
            dataModel={dataModel}
            timezone='America/New_York'
            handleSubmit={handleSubmit}
            dependencyMap={dependencyMap}
            getEvaluatedConstraints={handleEvaluateConstraints}
            submitButtonText='Update Element'
        />
    );
};

Props

Prop

Type

Description

Default

elementModel

ElementConfig

The configuration object from the data model that defines this element’s fields and structure.

Required

element

ElementResponse

The element object from the quote that is being edited.

Required

dataModel

DataModel

The entire resolved data model.

Required

timezone

string

The timezone for the quote or policy, essential for correct date/time handling.

Required

handleSubmit

(data: ElementRequest) => void

An optional callback triggered on submit with the ElementRequest payload.

undefined

dataTypes

DataTypeConfigRecord

Custom data types referenced by the element model.

undefined

coverageTerms

CoverageTermsConfigRecord

The configuration for coverage terms available to this element.

undefined

quote

QuoteResponse

The full quote object, used to enable conditional field rendering based on the state of other elements.

undefined

dependencyMap

QuoteDependencyMapResponse

An optional map of field dependencies. Required to enable the constraint evaluation feature.

undefined

getEvaluatedConstraints

(request, tenantLocator, locator) => Promise<ConstraintEvaluationResponse \| undefined>

An optional async function that calls the backend to evaluate constraints. Required for constraint evaluation.

undefined

hideAllFields

boolean

If true, hides all data fields in the form.

false

hideCoverageTerms

boolean

If true, hides the coverage terms section, even if they are defined in the model.

false

disabled

boolean

When true, disables the entire form.

false

isSubmitting

boolean

When true, disables the form to indicate a submission is in progress.

false

submitButtonText

string

Custom text for the submit button.

'Update'

…and other standard form control props (preventFormResetOnDisabled, validateOnSubmit, hideSubmitButton, id, titles).

State Management

ElementForm relies on internal state managed by useState and useEffect hooks.

  • Data Initialization: Form data is initialized using the getDefaultElementValues utility, which populates fields from the element response and its associated coverageTerms.

  • Constraint Evaluation: The mechanism is identical to InitializedTransactionForm. When a user changes a field that other fields depend on (as defined in dependencyMap), a useEffect hook calls the getEvaluatedConstraints function. The response is stored in an evaluatedConstraints state variable, which triggers a schema regeneration to update and disable dependent fields. The evaluatedConstraints are cleared on any subsequent form change to allow for re-evaluation.

  • Prop Synchronization: The component keeps a local copy of the element and coverageTerms props in state. A useEffect hook checks for differences between the incoming props and the local state. If a change is detected (e.g., after a parent component saves data), the form’s data is re-initialized to reflect the new state.

Validation

Validation is performed client-side using Ajv.

  • The validation schema is dynamically constructed by the dataModelToJSONSchema utility. This function considers the elementModel, dataTypes, timezone, and, importantly, the current quote object.

  • When constraint evaluation is active, the schema is augmented with the dependencyMap and the latest evaluatedConstraints response, which allows Ajv to enforce that dependent fields are read-only and have the correct calculated values.

  • The visibility of fields (controlled by hideAllFields and hideCoverageTerms) is also reflected in the final schema structure.

  • The translateError utility is used to convert validation errors into user-friendly messages.

Labels and Translations

The text for UI labels and validation messages can be customized.

UI Labels

Labels for sections and fields can be overridden by passing a titles object prop.

Key

Description

Default Value

coverageTerms

Title for the “Coverage Terms” section.

'Coverage Terms'

truthyLabel

Text for a “true” boolean value.

'Yes'

falsyLabel

Text for a “false” boolean value.

'No'