Input validation on profile page portal

sonalishind
Tera Contributor

Hi Team, 
I am new to service portal/widget. I have one requirement below.

Apply Validation Regex for all the profile fields that user can edit. 

  • Apply RegX validation for profile page.
    So could anyone please help to how to add the validation logic in below code.

    HTML:

    <div class="default-focus-outline">
    <div ng-if="!data.userExists" class="panel panel-default">
    <div class="panel-body wrapper-lg text-center">
    <p>${Requested user not found}</p>
    </div>
    </div>
    <div ng-if="data.userExists">
    <div class="panel panel-default">
    <div class="panel-body">
    <div class="row">
    <div class="col-xs-12 col-sm-4 text-center">
    <div class="row">
    <div class="avatar-extra-large avatar-container" style="cursor:default;">
    <div class="avatar soloAvatar bottom">
    <div class="sub-avatar mia" ng-style="avatarPicture"><i class="fa fa-user"></i></div>
    </div>
    </div>
    </div>
    <div class="row">
    <button ng-if="::connectEnabled()" ng-click="openConnectConversation()" type="button"
    class="btn btn-primary send-message"><span class="glyphicon glyphicon-comment pad-right"></span>${Message}</button>
    <!-- file upload -->
    <span ng-if="::data.isLoggedInUsersProfile">
    <input ng-show="false" type="file" accept="image/jpeg,image/png,image/bmp,image/x-windows-bmp,image/gif,image/x-icon,image/svg+xml" ng-file-select="attachFiles({files: $files})" />
    <button ng-click="uploadNewProfilePicture($event)"
    ng-keypress="uploadNewProfilePicture($event)" type="button"
    class="btn btn-default send-message">${Upload Picture}</button>
    </span>
    </div>
    </div>
    <div class="col-xs-12 col-sm-8">
    <h2>{{data.name}}</h2>
    <p ng-if="::displayField('sys_user', 'company', true)"><strong class="pad-right">${Company}</strong><sp-editable-field editable-by-user="false" table="sys_user" table-id="data.sysUserID" field-model="data.sysUserModel.company"></sp-editable-field></p>
    <p ng-if="::displayField('sys_user', 'title', true)"><strong class="pad-right">${Title}</strong><sp-editable-field editable-by-user="false" table="sys_user" table-id="data.sysUserID" field-model="data.sysUserModel.title"></sp-editable-field></p>
    <p ><strong class="pad-right">${Department}</strong><sp-editable-field editable-by-user="false" table="sys_user" table-id="data.sysUserID" field-model="data.sysUserModel.department"></sp-editable-field></p>
    <p ><strong class="pad-right">${Location}</strong><sp-editable-field editable-by-user="false" table="sys_user" table-id="data.sysUserID" field-model="data.sysUserModel.location"></sp-editable-field></p>

    </div>
    </div>
    </div>
    </div>
    <div class="row">
    <div ng-class="{'col-md-6': teamExists(), 'col-md-12': !teamExists()}" class="col-sm-12 col-xs-12">
    <div class="panel panel-default b" ng-if="getSysUserModelFields().length > 0">
    <div class="panel-heading">
    <h2 class="panel-title">
    <i class="fa fa-info-circle m-r-sm"></i>${About}
    </h2>
    </div>
    <div class="body padder-xs">
    <div class="list-group">
    <div ng-repeat="fieldModel in sysUserModelFields">

    <div class="list-group-item">
    <div>
    <sp-editable-field block="true" table="{{data.table}}" editable-by-user="data.isLoggedInUsersProfile" table-id="data.sysUserID" field-model="fieldModel"></sp-editable-field>
    </div>
    </div>
    </div>
    </div>
    </div>
    <div class="panel-footer clearfix" ng-if="data.dateTimeFormatChanged">
    <a id="refresh-to-complete-date-format-change" href="javascript&colon;void(0)"
    ng-click="reloadPage()" class="pull-right btn btn-primary"><i class="fa fa-refresh m-r-sm" aria-hidden="true"></i>${Refresh page to complete date/time format change}</a>
    </div>
    </div>
    </div>
    <div ng-if="teamExists()" class="col-md-6 col-sm-12 col-xs-12">
    <sp-widget widget="data.teamWidget"></sp-widget>
    </div>
    </div>
    <div class="row" ng-if="data.preferencesEnabled.preferencesPanelEnabled">
    <div class="col-sm-12 col-xs-12">
    <div class="panel panel-default b">
    <div class="panel-heading">
    <h2 class="panel-title">
    <i class="fa fa-cog m-r-sm"></i>${User preferences}
    </h2>
    </div>
    <div class="body padder-xs">
    <div class="list-group">
    <div class="list-group-item">
    <label>${Accessibility enabled} </label>
    <div class="input-switch">
    <input type="checkbox"
    ng-change="setUserPreferenceValue(data.userPreferences.accessibility)"
    ng-model="data.userPreferences.accessibility.value"
    name="accessibility-enabled" id="accessibility-enabled" aria-label="${Accessibility enabled}"/>
    <label class="switch" for="accessibility-enabled" ng-click="toggle($event, data.userPreferences.accessibility)" role="presentation" aria-hidden="true">
    <span class="sr-only">${Accessibility enabled}</span>
    </label>
    </div>
    </div>
    <div class="list-group-item" ng-if="data.showAnalytics">
    <label>${Enable Analytics} </label>
    <div class="input-switch">
    <input type="checkbox"
    ng-change="updateUserTracking(data.userPreferences.analytics)"
    ng-model="data.userPreferences.analytics.value"
    name="analytics-enabled" id="analytics-enabled" aria-label="${Enable Analytics}"/>
    <label class="switch" for="analytics-enabled" ng-click="toggle($event, data.userPreferences.analytics)" role="presentation" aria-hidden="true">
    <span class="sr-only">${Enable Analytics}</span>
    </label>
    </div>
    </div>
    <div class="list-group-item" ng-if="data.preferencesEnabled.timezoneEnabled">
    <label for="time_zone_picker_select">${Time zone}</label>
    <select id="time_zone_picker_select" class="form-control "
    name="time_zone_picker_select" ng-model="data.listProperties.timezone.current"
    ng-change="setPreferenceValue('timezone', data.listProperties.timezone.current.value)"
    ng-options="item as item.label for item in data.listProperties.timezone.list"/>
    </div>
    <div class="list-group-item" ng-if="data.preferencesEnabled.languageEnabled">
    <label for="language_picker_select">${Language}</label>
    <select id="language_picker_select" class="form-control"
    name="language_picker_select" ng-model="data.listProperties.language.current"
    ng-change="setPreferenceValue('language', data.listProperties.language.current.value)"
    ng-options="item as item.label for item in data.listProperties.language.list "/>
    </div>
    <div class="list-group-item" ng-if="data.preferencesEnabled.encryptionEnabled">
    <label for="encryption_picker_select">${Encryption}</label>
    <span class="fa fa-lock"></span>
    <select id="encryption_picker_select" class="form-control"
    name="encryption_picker_select" ng-model="data.listProperties.encryption.current"
    ng-change="setPreferenceValue('encryption', data.listProperties.encryption.current.value)"
    ng-options="item as item.label for item in data.listProperties.encryption.list "/>
    </div>
    <div class="list-group-item" ng-if="data.preferencesEnabled.mfaEnabled">
    <button class="btn btn-link" ng-click="triggerMFAConfigurationModal()" aria-haspopup="dialog">${Configure Multi-Factor Authentication}</button>
    </div>
    <div class="list-group-item" ng-if="data.preferencesEnabled.certAuthEnabled">
    <button class="btn btn-link" ng-click="triggerCertificateConfigurationModal()" aria-haspopup="dialog">${Register your client certificate}</button>
    </div>
    <div class="list-group-item" ng-if="data.notificationPreferences">
    <button class="btn btn-link" ng-click="c.openModal()" aria-haspopup="dialog">${Configure Alert and Notification Preference}</button>
    </div>
    </div>
    </div>
    <div class="panel-footer clearfix" ng-if="data.userPreferencesChanged">
    <a id="refresh-to-see-changes" href="javascript&colon;void(0)"
    ng-click="reloadPage()" class="pull-right btn btn-primary"><i class="fa fa-refresh m-r-sm" aria-hidden="true"></i>${Refresh to see changes}</a>
    </div>
    </div>
    </div>
    <script type="text/ng-template" id="mfaModalTemplate">
    <div>
    <div class="modal-header">
    <h1 class="h4 modal-title" style="display: inline-block">${Complete the steps below to enable multi-factor authentication}</h1>
    <i class="fa fa-close pull-right text-base" autofocus="true" tabindex="0" ng-click="dismissMFAConfigurationModal()" aria-label="${Close dialog}" role="button"></i>
    </div>
    <div class="modal-body">
    <iframe id="mfa-config-window" src="/google_auth_setup_dialog" width="100%" height="500px" frameBorder="0"></iframe>
    </div>
    </div>
    </script>
    <script type="text/ng-template" id="certAuthModalTemplate">
    <div>
    <div class="modal-header">
    <h1 class="h4 modal-title" id="certAuthModal" style="display: inline-block">${PIV/CAC Certificate Found}</h1>
    <i class="fa fa-close pull-right text-base" tabindex="0" ng-click="dismissCertAuthConfigurationModal()" aria-label="${Close dialog}" role="button"></i>
    </div>
    <div class="modal-body">
    <iframe id="cert-auth-config-window" src="/cert_confirm_page" width="100%" height="240px" frameBorder="0"></iframe>
    </div>

    </div>
    </script>
    </div>
    </div>
    </div>


    Client Controller:
    api.controller = function($scope, $element, $window, $location, $rootScope, $timeout, snAttachmentHandler, $http, spUtil, userPreferences, $filter, i18n, $uibModal, spModal, $q) {
         
     
        //START ALERT USER PREFENCE
        /* widget controller */
        var c = this;
        //open alert preference modal.
        c.openModal = function() {
                title: 'Configure Alert and Notification Preference',
                buttons: [{
                        label: '',
                        hide: true
                    },
                    {
                        label: '',
                        hide: true
                    }
                ],
                widgetInput: {},
                size: 'lg'
            }).then(function() {
                console.log('widget dismissed');
            });
        };
    $scope.$watch('data.dateTimeFormat', function() {
            if ($scope.data.dateTimeFormat != g_user_date_time_format)
                $scope.data.dateTimeFormatChanged = true;
        });

        $scope.uploadNewProfilePicture = function($event) {
            $event.stopPropagation();
            if ($event.keyCode === 9) {
                return;
            }
            var $el = $element.find('input[type=file]');
            $el.click();
        }

        $scope.attachFiles = function(files) {
            var file = files.files[0];

            var validImage = false;

            switch (file.type) {
                case 'image/jpeg':
                case 'image/png':
                case 'image/bmp':
                case 'image/x-windows-bmp':
                case 'image/gif':
                case 'image/x-icon':
                case 'image/svg+xml':
                    validImage = true;
                    break;
                default:
                    break;
            }

            if (!validImage) {
                alert(file.name + " " + i18n.getMessage("isn't a recognized image file format"));
                return;
            }

            snAttachmentHandler.create("live_profile", $scope.data.liveProfileID).uploadAttachment(file, {
                sysparm_fieldname: "photo"
            }).then(function(response) {
                var obj = {};
                obj.newAvatarId = response.sys_id;
                $      $rootScope.$broadcast("sp.avatar_changed", obj);
            });
        }

        $scope.avatarPicture = "";

       

        spUtil.recordWatch($scope, "sys_user", "sys_id=" + $scope.data.sysUserID);
        spUtil.recordWatch($scope, "live_profile", "sys_id=" + $scope.data.liveProfileID);

        $scope.connectEnabled = function() {
            return $scope.data.connectEnabled && !$scope.data.isLoggedInUsersProfile;
        }

        $scope.openUserProfile = function($event, userID) {
            $event.stopPropagation();
            $event.preventDefault();
            $location.search("id=user_profile&sys_id=" + userID);
        }

        $scope.getSysUserModelFields = function() {
            if ($scope.data.userExists) {
                return $scope.data.sysUserModelList
                    .filter(function(field) {
                        return $scope.displayField("sys_user", field.name);
                    });
            }
            return [];
        }
       


        $scope.data.showAnalytics = $scope.data.analytics_enabled && $scope.data.sp_analytics_plugin_active && !$scope.data.consent_popup_disabled && !$scope.data.ucm_encountered_exception && !NOW.user_impersonating && NOW.sp_analytics_portal_override != true;
        $scope.data.userPreferencesChanged = false;
        $scope.data.dateTimeFormatChanged = false;

        var getListValuesForProperty = function(endpoint, listProperty) {
                if (response && response.data && response.data.result && response.data.result.list) {
                    if (!listProperty.list)
                        listProperty.list = [];

                    listProperty.list = response.data.result.list;
                    if (response.data.result.current) {
                        if (!listProperty.current)
                            listProperty.current = {};
                        listProperty.current = $filter('filter')(listProperty.list, {
                            value: response.data.result.current
                        }, true)[0];
                    }
                }
            });
        };

        // list of user properties that are not user preferences
        $scope.data.listProperties = {
            timezone: {},
            encryption: {},
            language: {}
        }

        // initialize dropbox data
        getListValuesForProperty('timezone', $scope.data.listProperties.timezone);
        getListValuesForProperty('language', $scope.data.listProperties.language);
        getListValuesForProperty('encryption', $scope.data.listProperties.encryption);

        //set the user property
        $scope.setPreferenceValue = function(endpoint, value) {
                current: value,
                id: value
            }).then(function(response) {
                if (response && response.data && response.data.result) {
                    $scope.data.userPreferencesChanged = true;
                }
            });
        }

        //set the user preference value
        $scope.setUserPreferenceValue = function(userProperty) {
            userPreferences.setPreference(userProperty.key, userProperty.value).then(function() {
                $scope.data.userPreferencesChanged = true;
            });
        };

        $scope.updateUserTracking = function(userProperty) {
            $scope.setUserPreferenceValue(userProperty);
            $scope.server.get({
                action: "update_session_tracking_info",
                user_tracking: userProperty.value
            }).then(function() {
                NOW.usage_tracking.usage_tracking_allowed_for_session = userProperty.value;
            });
        };

        $scope.toggle = function(e, userProperty) {
            if (e.type === 'keypress' && e.keyCode === 32) {
                userProperty.value = !userProperty.value;
                $scope.setUserPreferenceValue(userProperty);
            }
        }

        $scope.reloadPage = function() {
            $window.location.reload(true);
        };

        $scope.teamExists = function() {
            return $scope.data.teamData.direct_reports.length > 0 ||
                $scope.data.teamData.members.length > 0 ||
                $scope.data.teamData.manager;
        }

        var models = {
            sys_user: $scope.data.sysUserModel,
            live_profile: $scope.data.liveProfileModel
        }

        $scope.displayField = function(tableName, field, isHeader) {


            if (!isHeader && fieldExcludes[tableName].indexOf(field) > -1) {
                //  if (fieldExcludes[tableName].indexOf(field) > -1){
                return false
            } else {
                return true;
            }

            //      if (models[tableName][field] && models[tableName][field].type === "boolean") return false;

            //  if ($scope.data.isLoggedInUsersProfile) {
            //      if (models[tableName][field] && models[tableName][field].readonly)
            //      return models[tableName][field].displayValue;
            //      else
            //          return models[tableName][field];
            //  } else {
            //      return models[tableName][field] && models[tableName][field].displayValue;
            //      }
        }

       

            $scope.server.update().then(function(response) {
                if (response.certHeader == 'false')
                    spUtil.addErrorMessage($scope.data.certErrorMsg);
                else {
                    });
               
        }


     $timeout(function() {
            $rootScope.$broadcast('finishedChanged', {
                profile: $scope.data.teamData
            });
        });

        $scope.sysUserModelFields = $scope.getSysUserModelFields();

        function createCloseMFAModalHandler() {
            // This is a hack. Wait for the inner iframe to load, then mock
            // the GlideDialogWindow close function to do the right thing. If it's not ready
            // after a second, try again 9 more times.
            var retryCount = 0;
            var maxRetries = 10;
            tryOverrideGlideDialogWindowClose();

            function tryOverrideGlideDialogWindowClose() {
                $timeout(function() {
                    var frameGlideDialogWindow = document.getElementById('mfa-config-window').contentWindow['GlideDialogWindow'];
                    if (!frameGlideDialogWindow) {
                        retryCount++;
                        if (retryCount >= maxRetries)
                            return;

                        tryOverrideGlideDialogWindowClose();
                        return;
                    }

                    frameGlideDialogWindow.get = function() {
                        return {
                            destroy: function() {
                                $scope.dismissMFAConfigurationModal();
                            }
                        }
                    };
                }, 1000);
            }
        }

        function createCloseCertAuthModalHandler() {
            // This is a hack. Wait for the inner iframe to load, then mock
            // the GlideDialogWindow close function to do the right thing. If it's not ready
            // after a second, try again 9 more times.
            var retryCount = 0;
            var maxRetries = 10;
            tryOverrideGlideDialogWindowClose();

            function tryOverrideGlideDialogWindowClose() {
                $timeout(function() {
                    var frameGlideDialogWindow = document.getElementById('cert-auth-config-window').contentWindow['GlideDialogWindow'];
                    if (!frameGlideDialogWindow) {
                        retryCount++;
                        if (retryCount >= maxRetries)
                            return;

                        tryOverrideGlideDialogWindowClose();
                        return;
                    }

                    frameGlideDialogWindow.get = function() {
                        return {
                            destroy: function() {
                                $scope.dismissCertAuthConfigurationModal();
                            }
                        }
                    };
                }, 1000);
            }
        }

    }
    Server side:
    if (input && input.action === "update_session_tracking_info") {
        gs.getSession().putProperty("usage_tracking_allowed_for_session", input.user_tracking);
        //return;
    }


    data.analytics_enabled = GlideProperties.getBoolean("glide.analytics.enabled");
    data.sp_analytics_plugin_active = GlidePluginManager.isActive('com.glide.service-portal.analytics');
    data.consent_popup_disabled = GlideProperties.getBoolean("glide.analytics.user.consent.popup.disabled");
    data.ucm_encountered_exception = gs.getSession().getProperty("ucm_encountered_exception") == true;

    // populate the 'data' object
    // e.g., data.table = $sp.getValue('table');
    data.sysUserID = $sp.getParameter("sys_id");
    if (!data.sysUserID)
        data.sysUserID = gs.getUser().getID();
    var sysUserGR = new GlideRecord("sys_user");
    data.userExists = sysUserGR.get(data.sysUserID) && sysUserGR.canRead();

    if (data.userExists) {
        sysUserGR = GlideScriptRecordUtil.get(sysUserGR).getRealRecord();
        data.table = sysUserGR.getRecordClassName();
        data.name = sysUserGR.getValue("name");
        var loggedInSysUserID = gs.getUser().getID();
        data.connectEnabled = GlidePluginManager().isActive('com.glide.connect');
        data.liveProfileID = "";
        data.dateTimeFormat = gs.getDateTimeFormat();

        //get live profile id for sending connect messages
        if (GlidePluginManager().isActive('com.glideapp.live_common')) {
            var liveProfileGR = new GlideRecord("live_profile");
            liveProfileGR.addQuery("document", data.sysUserID);
            liveProfileGR.query();
            if (liveProfileGR.next()) {
                data.liveProfileID = liveProfileGR.getValue("sys_id");
                data.liveProfileModel = $sp.getForm("live_profile", data.liveProfileID)._fields;
                // live_profile short_description is shown here as "Bio", so popup label/hint must reflect that
                if (data.liveProfileModel.short_description) {
                    data.liveProfileModel.short_description.label = gs.getMessage("Bio");
                    data.liveProfileModel.short_description.hint = gs.getMessage("Biography");
                }
            } else
                data.connectEnabled = false; //can't find a live profile for this user, so lets not integrate Connect
        }

        data.isLoggedInUsersProfile = loggedInSysUserID.equals(data.sysUserID);
        var sysUserForm = $sp.getForm(data.table, data.sysUserID);
        data.sysUserView = sysUserForm._view;
        data.sysUserModel = sysUserForm._fields;
        data.sysUserModelList = [];

        for (var i = 0; i < data.sysUserView.length; i++) {
            data.sysUserModelList.push(data.sysUserModel[data.sysUserView[i].name]);
        }

        data.directReports = [];
        data.teamData = {};
        data.teamData.direct_reports = [];
        data.teamData.members = [];

        if (!data.isLoggedInUsersProfile) {
            data.teamData.user = {
                sys_id: data.sysUserID
            }
        }

        //Calculate manager
        var managerGR = new GlideRecord("sys_user");
        if (managerGR.get(sysUserGR.getValue("manager"))) {
            data.teamData.manager = buildUser(managerGR);
        }

        //Calculate team
        if (data.teamData.manager) {
            var teamGR = new GlideRecord("sys_user");
            teamGR.addActiveQuery();
            teamGR.orderBy("name");
            teamGR.addQuery("manager", data.teamData.manager.sys_id);
            teamGR.addQuery("sys_id", "!=", data.sysUserID);
            teamGR.query();
            while (teamGR.next())
                data.teamData.members.push(buildUser(teamGR));
        }

        //Calculate direct reports
        var directReportGR = new GlideRecord("sys_user");
        directReportGR.addActiveQuery();
        directReportGR.orderBy("name");
        directReportGR.addQuery("manager", data.sysUserID);
        directReportGR.query();

        while (directReportGR.next())
            data.teamData.direct_reports.push(buildUser(directReportGR));

        data.teamWidget = $sp.getWidget('sp-my-team', {
            glyph: 'user',
            color: 'primary'
        });

        //get state preferences
        data.preferencesEnabled = getPreferencesEnabled();

        //get the user Preferences of the user
        data.userPreferences = getUserPreferences(data.sysUserID);

        //
        data.notificationPreferences = getNotificationPreferences();
    }

    //get the certificate header
    if (input.action == "certRegister") {
        var request = GlideTransaction.get().getRequest();
        var certHeader = request.getHeader("X-Client-Cert");
        if (!certHeader) {
            data.certHeader = "false";
            data.certErrorMsg = gs.getMessage("Failed to register PIV/CAC certificate to the user account. Please close your browser, ensure your card is inserted and try again");
        }
    }


    function buildUser(userGR) {
        return {
            email: userGR.getValue("email") || "",
            first_name: userGR.getValue("first_name"),
            last_name: userGR.getValue("last_name"),
            name: userGR.getValue("name"),
            phone: userGR.getValue("phone") || "",
            sys_id: userGR.getValue("sys_id")
        }
    }

    // returns the user preferences from the platform
    function getUserPreferences(userID) {
        var user = GlideUser.getUserByID(userID);
        return {
            accessibility: {
                key: 'glide.ui.accessibility',
                value: user.getPreference('glide.ui.accessibility') == 'true'
            },
            analytics: {
                key: 'enable_analytics',
                value: user.getPreference('enable_analytics') == 'true'
            }
        }
    }

    function getNotificationPreferences() {
        if (gs.getProperty('fedramp.req2.enable_alerts_notifications') === 'false') {
            return false;
        }
        var groupsForNotification = [
            "Customer Admins",
            "Customer Admins - No Supplies",
            "Customer Basic Access",
            "Customer Ordering",
            "Customer Ordering Service Only",
            "Customer Ordering Supplies Only"
        ];

        var user = gs.getUser();

        for (var i = 0; i < groupsForNotification.length; i++) {
            if (user.isMemberOf(groupsForNotification[i])) {
                return true;
            }
        }

        return false;
    }

    // read the proper state so we can show/hide preferences in the preferences table
    function getPreferencesEnabled() {
        var showEncryption = pm.isActive('com.glide.encryption') &&
                gs.getProperty('glide_encryption.cle_replatforming_with_kmf') !== 'opt_in' &&
                new SNC.ConcoursePickerGenerator().hasMultipleEncryptionChoices();

        //Enabling certificate based authentication per portal
        var portalRecord = $sp.getPortalRecord();
        if (portalRecord && (portalRecord.getValue('enable_certificate_based_authentication') == 1))
            var cert_based_auth = gs.getProperty('glide.authenticate.mutual.enabled', 'false') == 'true';

        return {
           $sp.getParameter('sys_id') == gs.getUserID(),

            //certain properties are visible in some cases
            languageEnabled: pm.isActive('com.glide.i18n') && gs.getProperty('glide.ui.language_picker.enabled', 'true') == 'true',
            timezoneEnabled: true,
            encryptionEnabled: showEncryption,
            mfaEnabled: gs.getProperty('glide.authenticate.multifactor', "false") == "true",
            certAuthEnabled: cert_based_auth
        }
    }



4 REPLIES 4

Huynh Loc
Mega Sage

Hello @sonalishind ,
We can use ng-pattern to apply Regex validation to inputs.

Example:
<form name="myForm">
<input type="text" name="pincode" ng-model="txtpin" ng-pattern="/^[0-9]{1,5}$/" required />
<span ng-show="myForm.pincode.$dirty && myForm.pincode.$error.pattern">
Only Numbers Allowed, Maximum 5 Characters
</span>
</form>

If this response was helpful, please consider marking it as Correct and Helpful. You may mark more than one reply as an accepted solution.



Hi  actually that fields fetch from user table that is not html input

_guinther
Tera Contributor

Use Dictionary Validation (Server-side)

How to do it

  1. Go to: System Definition → Dictionary

     
  2. Open the field (e.g., email, phone, title)

  3. Use one of the following:

    • Attributes → regex=your_regex_here

  4. Examples:
    • Email: ^[^\s@]+@[^\s@]+\.[^\s@]+$
    • Phone: ^\+?[1-9]\d{7,14}$

Hi,I want to apply logic in widget only