LFForm Quick Start

This guide helps you write reliable form scripts quickly with strong TypeScript hints and production-safe JavaScript patterns.

API References

Dive deeper into specific areas of the LFForm API:

  • Read API

    Learn how to retrieve field values and find fields.

  • Write API

    Discover how to modify fields and handle operations.

  • Events API

    Subscribe to and handle form, field, and lookup events.

  • Properties API

    Understand runtime form properties and state.

Additional Resources

  • Recipes

    Learn more about common patterns and solutions.

  • Custom HTML guide

    Check out our custom HTML and sandbox integrations.

What You Need

  • A form running the LFForm runtime (not classic designer)
  • Script logic running in form business logic

Identification Objects

Identification objects are objects containing information identifying which fields the interface should act on. Identification objects can have the following properties:

  • trackId: A unique identifier for a field. Note that the trackId is generated on field creation, so it won't be the same between different submission events.

    Example: {trackId: "59783b47-db11-4709-ba5a-1fb4833a1f73"}

  • fieldId: The field ID of a field.

    Example: {fieldId: 1}

  • variableName: The name of the variable associated with the field.

    Example: {variableName: "First_Name"}

  • variableId: The id of the variable associated with the field.

    Example: {variableId: "e7c9e10c-eeb0-4ce2-b3c6-26264c7fe655"}

  • index: If the field is in a collection or table, you can specify the index to get the exact field.

    Note: The index starts from 0.

    Example: {fieldId: 2, index: 2}

Best Practice Script Shape

Use one async entry point and await LFForm state-changing calls.

const formFields = {
  firstName: { fieldId: 10 },
  lastName: { fieldId: 11 },
  fullName: { fieldId: 12 },
};

const setFullName = async () => {
  const first = LFForm.getFieldValues(formFields.firstName);
  const last = LFForm.getFieldValues(formFields.lastName);

  if (!first || !last) return;
  await LFForm.setFieldValues(formFields.fullName, `${last}, ${first}`);
};

LFForm.onFieldChange(setFullName, formFields.firstName);
LFForm.onFieldChange(setFullName, formFields.lastName);

const main = async () => {
  if (LFForm.isReadonly || LFForm.isPrint || LFForm.isDisabled) return;
  await setFullName();
};

main().catch(console.warn);

Prefer fieldId for field identification

fieldId is the most reliable identifier, especially for table and collection fields.

Do not rely on variableName for table and collection fields.

Use index with fieldId for specific rows in repeatable contexts.

const formFields = {
  customerName: { fieldId: 100 },
  invoiceTotalColumn: { fieldId: 200 },
};

const allRowTotals = LFForm.getFieldValues(formFields.invoiceTotalColumn);
const firstRowTotal = LFForm.getFieldValues({ fieldId: 200, index: 0 });

Identification Object

Use one or more of these keys to target fields:

  • fieldId?: number
  • variableName?: string
  • variableId?: string
  • trackId?: string
  • index?: number

index starts at 0 for table/collection rows.

Read and Write Values

const formFields = {
  email: { fieldId: 300 },
  status: { fieldId: 301 },
  choices: { fieldId: 302 },
};

const email = LFForm.getFieldValues(formFields.email);
await LFForm.setFieldValues(formFields.status, 'Ready');
await LFForm.setFieldValues(formFields.choices, { value: ['A', 'B'] });

Handle Events

const formFields = {
  email: { fieldId: 300 },
  comments: { fieldId: 400 },
};

LFForm.onFieldChange(() => console.log('changed'), formFields.email);
LFForm.onFieldBlur(() => console.log('blurred'), formFields.email);

LFForm.onFormSubmission((event) => {
  const action = event?.data?.action?.value;
  if (action === 'Reject' && !LFForm.getFieldValues(formFields.comments)) {
    return { error: 'Comments are required for Reject.' };
  }
});

Get Submission Action on Submit

LFForm.onFormSubmission(async function (event) {
  // Get the value of the clicked submission button
  const userAction = event.data.action.value;
  const approvalComments = LFForm.getFieldValues({ fieldId: 2});
  if (userAction === "Reject" && approvalComments === "") {
    await LFForm.showFields({ fieldId: 2 });
    return { error: "Please add comments in order to approve." };
  } else {
    await LFForm.hideFields({ fieldId: 2 });
  }
});

Common Pitfalls

  • Not awaiting mutating methods: setFieldValues, showFields, hideFields, addRow, etc.
  • Writing to fields in readonly/print contexts
  • Assuming table/collection calls always return a scalar (they may return arrays)
  • Omitting index when targeting a specific row

Where to Go Next

Dive deeper into specific areas of the LFForm API:

  1. Read API - Learn how to retrieve field values and find fields
  2. Write API - Discover how to modify fields and handle operations
  3. Events API - Subscribe to and handle form, field, and lookup events
  4. Properties API - Understand runtime form properties and state

Learn more about common patterns and solutions on our Recipes page

For custom HTML and sandbox integrations, check out our Custom HTML guide.