Product Line Editor Wrapper

If it’s necessary to change the behavior of the Product Line Editor, the developer can wrap it in a custom “wrapper” component and define certain injections or trigger certain behaviors via the Editor’s controller.

Product Line Editor’s Controller and its methods could be controlled by using a reference.

🌐
productLineEditorWrapper.html
Copy to clipboard
<template>
  <finblick-product-line-editor lwc:ref="lineEditor"
                                record-id={recordId}
                     object-api-name={objectApiName}>
  </finblick-product-line-editor>

  <button onclick={handleCancel}>Cancel</button>
</template>
📄
productLineEditorWrapper.js
Copy to clipboard
import { LightningElement, api } from 'lwc';

export default class ProductLineEditorWrapper extends LightningElement {
  @api recordId;
  @api objectApiName;
  
  handleCancel(event) {
    //accessing editor's controller 
    this.refs.lineEditor.controller.cancel();  
  }
}

General Information #

Product Line Editor attributes #

NameTypeDescription
recordIdIdId of a record Line Editor is used for.
objectApiNameStringObject API Name of an object Line Editor is used for.
controllerClassController gives developer an ability to:
– Manipulate Product Line Editor’s data and UI from the outside;
– Inject custom logic to fire during certain triggers.

Product Line Editor Methods #

NameDescription
lifecycleeventFires when a Lifecycle Event has happened.

Lifecycle Events #

Lifecycle Events are events that fire at certain points of component’s lifecycle. All lifecycle events’ details contain the following parameters:

📄
Copy to clipboard
{
  eventName: "eventName",
  ...event-dependant parameters (if any)
}

init #

“init” event fires when the line editor’s engine is initiated.

Record isn’t loaded at this point yet.

Controller methods #

addLineItems #

Arguments

  • lineItems – list of line items to add.

Description:

Adds line items with provided payload.

By default, line items are added at the end of last section, in the order provided.

sectionIndex” key could be added to each of the line items to add them to the end of a specific section instead.

Matching will be executed for all line items containing “productId” key.

Example:

📄
Copy to clipboard
const someItem = {discount: 4};
const blankItem = {};
const targetedSectionItem = {
  sectionIndex: 1,
  customProductName: "Test"
}
await addLineItems([someItem, blankItem, targetedSectionItem]);

editLineItem #

Arguments

  • data – data to update on line item.

Returns an updated line item.

Description: Updates a line item with provided data, while keeping all other fields unchanged.

Die Daten müssen die Schlüssel „sectionIndex“ und „productIndex“ enthalten. Wenn ohne Sektionen gearbeitet wird, ist „sectionIndex“ gleich 0.

If data contains “productId” key with value that’s different from a blank string, matching will be executed for the item.

If data contains “productId” key with a blank string value (“”), “Product” lookup will be cleared. If the targeted line item exists in a DB, it will be deleted upon saving.

Example:

📄
Copy to clipboard
const someItem = {
  sectionIndex: 1,
  productIndex: 2,
  unitPrice: 800
};
await editLineItem(someItem);

dragLineItem #

Arguments

  • oldPlacement – placement of line item to be moved.
  • newPlacement – placement to move line item to.

Returns a moved line item.

Description: Moves a line item from one place to another.

Example:

📄
Copy to clipboard
const oldPlacement = {
  sectionIndex: 2,
  productIndex: 3
};
const newPlacement = {
  sectionIndex: 1,
  productIndex: 0
};
dragLineItem(oldPlacement, newPlacement);

deleteLineItem #

Arguments

  • placement – placement of the item to be deleted.

Returns a deleted line item.

Description: Deletes a line item at a specified place.

Example:

📄
Copy to clipboard
const placement = {
  sectionIndex: 2,
  productIndex: 3
};
deleteLineItem(placement);

addSection #

Description: If working without sections, enables them and groups all existing line items in a single section. Otherwise, adds a section at the end of list.

Example:

addSection();

editSection #

Arguments

  • data – data to update on section.

Description: Updates a section with provided data.

Data must contain “sectionIndex“.

If it’s necessary to update section’s line items, use editLineItem instead.

Example:

📄
Copy to clipboard
const data = {
  sectionIndex: 1,
  name: "Custom Section Name"
};
editSection(data);

dragSection #

Arguments

  • oldSectionIndex – index of a section to be moved.
  • newSectionIndex – index to move section to.

Description: Moves a section from one place to another.

Example:

📄
Copy to clipboard
const oldSectionIndex = 1;
const newSectionIndex = 2;
dragSection(oldSectionIndex, newSectionIndex);

deleteSection #

Arguments

  • sectionIndex – index of a section to be deleted.

Description: Deletes a section at a specified place.

If trying to delete section normally, a confirmation modal will appear.

This method doesn’t open a modal, and will delete the section immediately.

Example:

📄
Copy to clipboard
const sectionIndex = 4;
deleteSection(sectionIndex);

removeAllSections #

Description: If working with sections, disables them.

This action doesn’t delete any items. It groups all existing items in an invisible for user section.

Example:

removeAllSections();

cancel #

Description: Cancels any changes made.

Example:

cancel();

saveLineItems #

Returns an object containing the following keys:

  • sections – list of sections;
  • uiSettings – reserved for internal use.

Description: Saves any changes made.

Example:

📄
Copy to clipboard
const record = await saveLineItems();
console.log(JSON.stringify(record.sections));

setLoading #

Arguments

  • isLoading – loading state (true/false).

Description: Enables/disables component loading.

Example:

📄
Copy to clipboard
setLoading(true);
//wait for some data to load
setLoading(false);

setReadMode #

Arguments

  • readMode – mode to set (true/false)

Description: Sets component’s mode to either read mode (true) or edit mode (false).

Example:

📄
Copy to clipboard
setReadMode(true);
//do some changes while user can't edit
setReadMode(false);

expandLineItem #

Arguments

  • placement – placement of a line item to be expanded.

Description: Expands a line item at a specific placement, showing additional fields.

Example:

📄
Copy to clipboard
const placement = {
  sectionIndex: 2,
  productIndex: 3
};
expandLineItem(placement);

expandAllLineItems #

Description: Expands all line items.

shrinkAllLineItems #

Description: Shrinks all line items.

Example:

📄
Copy to clipboard
shrinkAllLineItems();
//do some changes while nobody sees
expandAllLineItems();

injectLifecycleHook #

Arguments

  • eventName – name of the event that triggers an injection.
  • overwriteFunction – custom function that will be executed when the event is triggered.

Description: Allows a custom functionality to happen during certain injection events.

Examples will be provided in the next section.

Injection event names #

This is the list of all supported injections, when they are triggered, and usage examples.

addlineitems #

Arguments

  • lineItems – array of line items that are to be added.

Is triggered when:

  • “Add Line Item” is pressed – adds a blank line;
  • “Save” is pressed when adding multiple line items;
  • “Product” lookup is selected for a line item;
  • Controller’s “addLineItems” function is called.

If any of the items contains a non-blank “productId” field, injection is fired after matching. Otherwise, injection is fired immediately.

Injection is fired before totals for items are calculated.

Example:

📄
Copy to clipboard
const injectionFunction = lineItems => {
  lineItems.forEach(lineItem => lineItem.customProductName = "test");
};
injectLifecycleHook("addlineitems", injectionFunction);

save #

Arguments

  • sections – sections containing line items that are to be saved.

Is triggered when:

  • “Save” button is pressed;
  • Controller’s “saveLineItems” function is called.

Injection happens before changes are saved to DB.

Example:

📄
Copy to clipboard
const injectionFunction = sections => {
  sections.forEach((section, index) => section.name = "test" + index);
};
injectLifecycleHook("save", injectionFunction);

Injection code example #

🌐
productLineEditorWrapper.html
Copy to clipboard
<template>
    <finblick-product-line-editor lwc:ref="lineEditor"
                                  record-id={recordId}
                                  object-api-name={objectApiName}
                                  onlifecycleevent={handleLifecycleEvent}>
    </finblick-product-line-editor>
</template>
📄
productLineEditorWrapper.js
Copy to clipboard
import { LightningElement, api } from 'lwc';
import { ShowToastEvent } from "lightning/platformShowToastEvent";

export default class ProductLineEditorWrapper extends LightningElement {
    @api recordId;
    @api objectApiName;

    handleLifecycleEvent(event) {
        switch (event.detail.eventName) {
            case 'init':
                this.handleEngineInit(event);
                break;
            default:
                break;
        }
    }

    handleEngineInit(event) {
        const controller = this.refs.lineEditor.controller;
        
        controller.injectLifecycleHook('addlineitems', this.addLineItemsInjection);
        controller.injectLifecycleHook('save', this.saveInjection.bind(this));
    }

    addLineItemsInjection = (lineItems) => {
        if (lineItems.some(lineItem => lineItem.productId)) {
            const loyaltyDiscount = 15;
            lineItems.forEach(lineItem => lineItem.discount = loyaltyDiscount);

            const toastEvent = new ShowToastEvent({
                title: "Loyalty discount applied.",
                message: `We've applied a ${loyaltyDiscount}% discount to item's you've just added as a sign of gratitude.`,
                variant: "success"
            });
            this.dispatchEvent(toastEvent);
        }
    }

    saveInjection(sections) {
        const toastEvent = new ShowToastEvent({
            title: "Save Injection Triggered.",
            message: "Triggered a save injection",
            variant: "info"
        });
        this.dispatchEvent(toastEvent);
    }
}

Additional Information #

Section attributes #

Parameters intended for internal use only are omitted

NameTypeDescription
nameStringSection name.
sectionIndexNumberSection’s index.
totalNumberSection’s total price.
lineItemsArraySection’s items. Item’s structure is described below.

Line item attributes #

Parameters intended for internal use only are omitted

NameTypeRequiredDescription
idIdLine Item’s record Id.
unitPriceNumberYesLine Item’s unit price.
unitTypeStringLine Item’s unit type. Restricted to the values of “Unit Type” global value set.
quantityNumberYesLine Item’s quantity.
discountNumberLine Item’s discount.
totalPriceNumberLine Item’s total price.
descriptionStringLine Item’s description.
customProductNameStringLine Item’s display name.
priceBookEntryIdIdFor Orders and QuotesLine Item’s Price Book Entry Id.
productIdIdYesLine Item’s Product Id.
productNameStringLine Item’s Product name.
taxRuleObjectLine Item’s Tax Rule. Contains the following attributes:
id – Tax Rule’s Id;
name – Tax Rule’s name;
percentage – Tax Rule’s rate.
dynamicFieldsObjectLine Item’s dynamic fields. These fields are used in dynamic sections.
Attributes are fields’ API names.
sectionIndexNumberLine Item’s section’s index.
productIndexNumberLine Item’s index within section.

Placement attributes #

NameType
sectionIndexNumber
productIndexNumber

What are your feelings

Updated on October 29, 2025
This site is registered on wpml.org as a development site. Switch to a production site key to remove this banner.