Skip to main content

Notifications

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

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




    
    


    
    

  • Suggested answer
    cleon37 Profile Picture
    cleon37 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 :)

  • Juliet Zhu Profile Picture
    Juliet Zhu 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

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

December Spotlight Star - Muhammad Affan

Congratulations to a top community star!

Top 10 leaders for November!

Congratulations to our November super stars!

Community AMA December 12th

Join us as we continue to demystify the Dynamics 365 Contact Center

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 291,253 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 230,188 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans