ManageNegotiableQuoteTemplate Container
The ManageNegotiableQuoteTemplate container provides the interface for managing quote templates with template-specific actions and details.
Version: 1.1.2
Configuration
Section titled “Configuration”The ManageNegotiableQuoteTemplate container provides the following configuration options:
| Parameter | Type | Req? | Description |
|---|---|---|---|
onActionsButtonClick | function | No | Callback when an action button is clicked. Use for custom action handling, analytics, or to add additional behavior when users trigger template actions. |
onSendForReview | function | No | Callback when the quote template is sent for review. Use to implement custom notifications, trigger follow-up workflows, or integrate with external systems. |
maxFiles | number | No | Sets the maximum number of files that can be attached when sending a quote template for review. Use to enforce attachment limits and prevent excessive uploads. |
maxFileSize | number | No | Sets the maximum file size in bytes for quote template attachments. Use to prevent large uploads and provide consistent UX for file validation. |
acceptedFileTypes | string[] | No | Specifies an array of MIME types allowed for quote template attachments (for example \['application/pdf', 'image/jpeg', 'image/png'\]). Use to restrict uploads to supported document types. |
initialData | object | No | Preloaded data for the model before backend data is fetched. Use for testing, SSR, or improving initial load. |
This container exposes the following slots for customization:
| Slot | Type | Required | Description |
|---|---|---|---|
TemplateName | SlotProps | No | Customizes the template name area, including the rename affordance. Use to change how the template name is displayed or to add additional metadata next to it. |
TemplateStatus | SlotProps | No | Customizes how the template status is displayed. Use to change the status label, badge styling, or status-specific messaging. |
Banner | SlotProps | No | Customizes the alert banner area for template state changes and actions. Use to add custom messaging for template lifecycle events (for example, updated, in review, accepted). |
Details | SlotProps | No | Customizes the template details section. Use to add or reorder template metadata and apply custom formatting. |
ActionBar | SlotProps | No | Customizes the action bar for quote template operations. Use to add custom actions, reorder controls, or integrate with external workflows. |
ReferenceDocuments | function | No | Customizes the reference documents section. Use to replace the default list UI or to customize add, edit, and remove behavior. |
ItemsTable | SlotProps | No | Customizes the template items section container. Use to wrap or replace the default items table layout. |
ItemsQuotedTab | SlotProps | No | Customizes the Items Quoted tab for template items. Use to add additional item details, custom actions, or supplemental content. |
CommentsTab | SlotProps | No | Customizes the Comments tab for quote template discussions. Use to change how comments are displayed or to add validation and formatting. |
HistoryLogTab | SlotProps | No | Customizes the History Log tab for template activity. Use to filter, group, or extend the activity feed. |
CommentsTitle | SlotProps | No | Customizes the comments section heading for a quote template. Use to add help text or additional context for commenters. |
Comments | SlotProps | No | Customizes the comments section content for a quote template. Use to replace the default comments UI or to integrate with an external commenting system. |
AttachFilesField | function | No | Customizes the file attachment input for a quote template. Use to add drag-and-drop UX, validation messaging, or integrations with document storage. |
AttachedFilesList | function | No | Customizes how attached files are displayed for a quote template. Use to add previews, custom removal UX, or external viewers. |
HistoryLogTitle | SlotProps | No | Customizes the history log section heading for a quote template. Use to add contextual help or status indicators. |
HistoryLog | SlotProps | No | Customizes the history log content for a quote template. Use to change formatting, sorting, or grouping of history entries. |
Footer | function | No | Customizes the footer actions for quote template management. Use to change submit and accept controls, add validation steps, or show custom status messaging. |
ShippingInformationTitle | SlotProps | No | Customizes the shipping information section heading for a quote template. Use to add icons, tooltips, or additional context. |
ShippingInformation | function | No | Customizes the shipping information section for a quote template. Use to replace the default display or integrate with custom shipping workflows. |
The following example demonstrates how to use the ManageNegotiableQuoteTemplate container:
import { render as provider } from '@dropins/storefront-quote-management/render.js';import { ManageNegotiableQuoteTemplate } from '@dropins/storefront-quote-management/containers/ManageNegotiableQuoteTemplate.js';
await provider.render(ManageNegotiableQuoteTemplate, { acceptedFileTypes: ACCEPTED_FILE_TYPES, slots: { ShippingInformation: (ctx) => { // Append the address error container to the shipping information container ctx.appendChild(addressErrorContainer); const shippingInformation = document.createElement('div'); shippingInformation.classList.add('negotiable-quote-template__select-shipping-information'); ctx.appendChild(shippingInformation); const progressSpinner = document.createElement('div'); progressSpinner.classList.add('negotiable-quote-template__progress-spinner-container'); progressSpinner.setAttribute('hidden', true); ctx.appendChild(progressSpinner); UI.render(ProgressSpinner, { className: 'negotiable-quote-template__progress-spinner', size: 'large', })(progressSpinner); ctx.onChange((next) => { // Remove existing content from the shipping information container shippingInformation.innerHTML = ''; const { templateData } = next; if (!templateData) return; if (!templateData.canSendForReview) return; if (templateData.canSendForReview) { accountRenderer.render(Addresses, { minifiedView: false, withActionsInMinifiedView: false, selectable: true, className: 'negotiable-quote-template__shipping-information-addresses', selectShipping: true, defaultSelectAddressId: 0, showShippingCheckBox: false, showBillingCheckBox: false, onAddressData: (params) => { const { data, isDataValid: isValid } = params; const addressUid = data?.uid; if (!isValid) return; if (!addressUid) return; progressSpinner.removeAttribute('hidden'); shippingInformation.setAttribute('hidden', true); addQuoteTemplateShippingAddress({ templateId: quoteTemplateId, shippingAddress: { customerAddressUid: addressUid, }, }).finally(() => { progressSpinner.setAttribute('hidden', true); shippingInformation.removeAttribute('hidden'); }); }, onSubmit: (event, formValid) => { if (!formValid) return; const formValues = getFormValues(event.target); const [regionCode, _regionId] = formValues.region?.split(', ') || []; // iterate through the object entries and combine the values of keys that have // a prefix of 'street' into an array const streetInputValues = Object.entries(formValues) .filter(([key]) => key.startsWith('street')) .map(([_, value]) => value); const addressInput = { firstname: formValues.firstName, lastname: formValues.lastName, company: formValues.company, street: streetInputValues, city: formValues.city, region: regionCode, postcode: formValues.postcode, countryCode: formValues.countryCode, telephone: formValues.telephone, }; // These values are not part of the standard address input const additionalAddressInput = { vat_id: formValues.vatId, }; progressSpinner.removeAttribute('hidden'); shippingInformation.setAttribute('hidden', true); addQuoteTemplateShippingAddress({ templateId: quoteTemplateId, shippingAddress: { address: { ...addressInput, additionalInput: additionalAddressInput, }, customerNotes: formValues.customerNotes, }, }) .catch((error) => { addressErrorContainer.removeAttribute('hidden'); UI.render(InLineAlert, { type: 'error', description: `${error}`, })(addressErrorContainer); }) .finally(() => { progressSpinner.setAttribute('hidden', true); shippingInformation.removeAttribute('hidden'); }); }, })(shippingInformation); } }); }, }})(block);