Hello
I'm starting in POS development, I hope you can guide me in how I can apply a validation of a custom control. Taking /RetailSDK/POS/CustomerAddEdit as an example
I want to validate that based on the value of the variable "customerIsPerson" it can be validated that the "ssn" property only allows to capture exactly 12 characters. Otherwise, only exactly 10 characters are captured in the "organizationid" property.
Is it possible to do this in this typescript scope?
CustomFieldSection.ts
import { CustomerAddEditCustomControlBase, ICustomerAddEditCustomControlState, ICustomerAddEditCustomControlContext, CustomerAddEditCustomerUpdatedData } from "PosApi/Extend/Views/CustomerAddEditView"; import { ObjectExtensions } from "PosApi/TypeExtensions"; import { ProxyEntities } from "PosApi/Entities"; import * as Controls from "PosApi/Consume/Controls"; export default class CustomFieldsSection extends CustomerAddEditCustomControlBase { public ssn: Observable; public organizationId: Observable; public isVip: boolean; public customerIsPerson: Observable; public toggleSwitch: Controls.IToggle; private static readonly TEMPLATE_ID: string = "Microsoft_Pos_Extensibility_Samples_CustomFieldsSection"; constructor(id: string, context: ICustomerAddEditCustomControlContext) { super(id, context); this.ssn = ko.observable(""); this.organizationId = ko.observable(""); this.isVip = false; this.customerIsPerson = ko.observable(false); this.ssn.subscribe((newValue: string): void => { this._addOrUpdateExtensionProperty("ssn", { StringValue: newValue }); }); this.organizationId.subscribe((newValue: string): void => { this._addOrUpdateExtensionProperty("organizationId", { StringValue: newValue }); }); this.customerUpdatedHandler = (data: CustomerAddEditCustomerUpdatedData) => { this.customerIsPerson(data.customer.CustomerTypeValue === ProxyEntities.CustomerType.Person); }; } /** * Binds the control to the specified element. * @param {HTMLElement} element The element to which the control should be bound. */ public onReady(element: HTMLElement): void { ko.applyBindingsToNode(element, { template: { name: CustomFieldsSection.TEMPLATE_ID, data: this } }); let toggleOptions: Controls.IToggleOptions = { labelOn: this.context.resources.getString("string_1357"), labelOff: this.context.resources.getString("string_1358"), checked: this.isVip, enabled: true, tabIndex: 0 }; let toggleRootElem: HTMLDivElement = element.querySelector("#isVipToggle") as HTMLDivElement; this.toggleSwitch = this.context.controlFactory.create(this.context.logger.getNewCorrelationId(), "Toggle", toggleOptions, toggleRootElem); this.toggleSwitch.addEventListener("CheckedChanged", (eventData: { checked: boolean }) => { this.toggleVip(eventData.checked); }); } /** * Initializes the control. * @param {ICustomerDetailCustomControlState} state The initial state of the page used to initialize the control. */ public init(state: ICustomerAddEditCustomControlState): void { if (!state.isSelectionMode) { this.isVisible = true; this.customerIsPerson(state.customer.CustomerTypeValue === ProxyEntities.CustomerType.Person); } } /** * Toggles Vip property. * @param {boolean} checked Indicates if vip is checked or not. */ public toggleVip(checked: boolean): void { this._addOrUpdateExtensionProperty("isVip", { BooleanValue: checked }); } /** * Gets the property value from the property bag, by its key. Optionally creates the property value on the bag, if it does not exist. */ private _addOrUpdateExtensionProperty(key: string, newValue: ProxyEntities.CommercePropertyValue): void { let customer: ProxyEntities.Customer = this.customer; let extensionProperty: ProxyEntities.CommerceProperty = Commerce.ArrayExtensions.firstOrUndefined(customer.ExtensionProperties, (property: ProxyEntities.CommerceProperty) => { return property.Key === key; }); if (ObjectExtensions.isNullOrUndefined(extensionProperty)) { let newProperty: ProxyEntities.CommerceProperty = { Key: key, Value: newValue }; if (ObjectExtensions.isNullOrUndefined(customer.ExtensionProperties)) { customer.ExtensionProperties = []; } customer.ExtensionProperties.push(newProperty); } else { extensionProperty.Value = newValue; } this.customer = customer; } }
CustomFieldSection.html
I answer to myself
Getting involved in the Knockout JavaScript library I was able to identify that in the native method "subscribes" I can implement my logic.
this.rfc.subscribe((newValue: string): void => { if ( newValue.length != this.rfcLength() ) { let message: string = "El RFC debe tener " this.rfcLength() "caracteres"; MessageDialog.show(this.context, "Error RFC",message); } else this._addOrUpdateExtensionProperty("EMAILOPTIN", { StringValue: newValue }); });
Similarly when saving changes to the client, this functionality does not run, so I had to create a POS trigger extension of type PreCustomerSaveTrigger to be precise.
Based on the RetailSDK examples, my extension is this way. Notice that I'm still validating the value of a custom field so I refer to Extension Properties.
import * as Triggers from "PosApi/Extend/Triggers/CustomerTriggers"; import { ClientEntities, ProxyEntities } from "PosApi/Entities"; import { ObjectExtensions, StringExtensions } from "PosApi/TypeExtensions"; import { GetCustomerClientRequest, GetCustomerClientResponse, CreateCustomerServiceRequest, CreateCustomerServiceResponse } from "PosApi/Consume/Customer"; import { ShowMessageDialogClientRequest, ShowMessageDialogClientResponse } from "PosApi/Consume/Dialogs"; export default class PreCustomerSaveTrigger extends Triggers.PreCustomerSaveTrigger { public execute(options: Triggers.IPreCustomerSaveTriggerOptions): Promise { console.log("Executing PreEndTransactionTrigger with options " JSON.stringify(options) "."); let rfc: string = ""; // let datos: string = JSON.stringify(options); let customer: ProxyEntities.Customer = options.customer; let rfcLen = customer.CustomerTypeValue === ProxyEntities.CustomerType.Person ? 13 : 12; let extensionProperty: ProxyEntities.CommerceProperty = Commerce.ArrayExtensions.firstOrUndefined(customer.ExtensionProperties, (property: ProxyEntities.CommerceProperty) => { return property.Key === "EMAILOPTIN"; }); if (!ObjectExtensions.isNullOrUndefined(extensionProperty)) rfc = extensionProperty.Value.StringValue; if (rfc.length == rfcLen) return Promise.resolve({ canceled: false, data: new CreateCustomerServiceResponse(customer) }); // let rfc: string = (document.getElementById("customerRFCInput") as HTMLInputElement).value let showMessageDialogClientRequestOptions: ClientEntities.Dialogs.IMessageDialogOptions = { title: "POS ERROR!", subTitle: "RFC: " rfc, message: "EL RFC DEBE TENER" rfcLen " CARACTERES", button1: { id: "Button1Close", label: "OK", result: "OKResult" }, button2: { id: "Button2Cancel", label: "Cancel", result: "CancelResult" } }; let showMessageDialogClientRequest: ShowMessageDialogClientRequest = new ShowMessageDialogClientRequest(showMessageDialogClientRequestOptions); return this.context.runtime.executeAsync(showMessageDialogClientRequest) .then((showMessageDialogClientResponse: ClientEntities.ICancelableDataResult): Promise<ClientEntities.ICancelableDataResult> => { // Save the attribute value depending on the dialog result. let messageDialogResult: ClientEntities.Dialogs.IMessageDialogResult = showMessageDialogClientResponse.data.result; let result: Promise<ClientEntities.ICancelableDataResult>; result = Promise.resolve({ canceled: true, data: new CreateCustomerServiceResponse(null) }); return result; }); } }
I hope someone will serve you my solution :)
Hi Carlos,
Thank you for visiting our community. I will leave this question for other community members (developers) to answer. Let's see if anybody has experienced the same and can advise for you anything.
Thanks,
Juliet Zhu
Stay up to date on forum activity by subscribing. You can also customize your in-app and email Notification settings across all subscriptions.
André Arnaud de Cal... 291,253 Super User 2024 Season 2
Martin Dráb 230,188 Most Valuable Professional
nmaenpaa 101,156