web
You’re offline. This is a read only version of the page.
close
Skip to main content
Community site session details

Community site session details

Session Id :
Supply chain | Supply Chain Management, Commerce
Suggested answer

How to validate the length of a custom field dynamically, based on the value of a field in the CustomerAddEdit form

(0) ShareShare
ReportReport
Posted on by

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 have the same question (0)
  • Juliet Zhu Profile Picture
    on at
    RE: How to validate the length of a custom field dynamically, based on the value of a field in the CustomerAddEdit form

    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

  • Suggested answer
    cleon37 Profile Picture
    on at
    RE: How to validate the length of a custom field dynamically, based on the value of a field in the CustomerAddEdit form

    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 :)

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Abhilash Warrier – Community Spotlight

We are honored to recognize Abhilash Warrier as our Community Spotlight honoree for…

Leaderboard > Supply chain | Supply Chain Management, Commerce

#1
CA Neeraj Kumar Profile Picture

CA Neeraj Kumar 865

#2
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 289 Super User 2025 Season 2

#3
Sagar Suman Profile Picture

Sagar Suman 230 Super User 2025 Season 2

Last 30 days Overall leaderboard

Featured topics

Product updates

Dynamics 365 release plans