@patricktahumegmail-com

@patricktahumegmail-com

Forum Replies Created

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • in reply to: css on blazor componet not applying #104017
    Patrick Hume
    Participant

    ah I see, thank you that helps explain it, I understand why it wasn’t working now, 🙂

    Patrick Hume
    Participant

    I thought I would update this with a complete solution with a few weeks for a better UXI experience.

    This ensures the password field is not red on page load, then if the user types in it and then deletes its contents it will then appear red to indicate that it is required the same behaviour as other required fields, also fix the styling so that the password *’s are indented and appears the same as the default blazor form-control class, also adds the field highlight when password field is selected. The submit button is only enabled when the complexity is ‘Strong’, and when the submit is clicked it displays a spinning bootstrap icon on the submit button and disables it to prevent re-clicking. Assumes the submit action will call a service that returns a result object or response, this can then be used to display the smart blazor badge to give feedback on the Ui to the user.

    I hope this helps someone one day

    complexityCheck.js

    const symbols = /['<>@!#$%^&*()_+\]\[\{}?:;|'"\\,.\/~`\-=']+/;
    const numerical = /.*[0-9].*/;
    const upperCase = /.*[A-Z].*/;
    const lowerCase = /.*[a-z].*/;
    
    (function (global) {
        global.customStrength = function (dotNetObject) {
            const allowedSymbols = '<>@!#$%^&*()_+[]{}?:;|\'"\\,./~`-=';
            const passwordField = document.querySelectorAll("smart-password-text-box")[0];
            const passwordConfirm = document.querySelectorAll("smart-password-text-box")[1];
            // Remove the red border on the page load
            passwordConfirm.style.border = '';
            // Set the border to red if the field is cleared and outline green if the field has a value
            // Assumes that any value will be the same is the same as the first password field & relies on 
            // MVC data attestations [Compare( to enforce this at time of form submit
            passwordConfirm.addEventListener('change', function (event) {
                if (event.detail.value) {
                    this.style.border = "#26b050 solid 1.5px";
                } else {
                    this.style.border = "red solid 3px";
                }
            });
            passwordField.messages = {
                'en': {
                    'passwordStrength': 'Password strength',
                    'short': 'Short',
                    'init': 'init',
                    'weak': 'complexity Week - missing at least 1 symbol, ' + allowedSymbols,
                    'far': 'complexity Fair - missing at least 1 numerical value, 0 - 9',
                    'better': 'complexity Better - missing at least 1 upper case characture, A- Z',
                    'good': 'complexity Good - missing at least 1 lower case characture, a - z',
                    'strong': 'Strong =)',
                    'showPassword': 'Show password'
                }
            };
            // indent password text to match the styling of other from controls 
            passwordField.style.textIndent = '0.7rem'
            setTimeout(function () {
                passwordField.passwordStrength = function (password, allowableSymbols) {
                    const passwordLength = password.length;
                    let message = null;
                    //debugger;                
                    passwordField.children[0].classList.remove("smart-password-better");
                    if (passwordLength < 7) {
                        message = 'short';
                    } else if (!new RegExp(symbols).exec(password)) {
                        message = 'weak';
                    } else if (!new RegExp(numerical).exec(password)) {
                        message = 'far';
                    } else if (!new RegExp(upperCase).exec(password)) {
                        message = 'better';
                    } else if (!new RegExp(lowerCase).exec(password)) {
                        message = 'good';
                    }
                    //console.log(message);
                    if (message) {
                        dotNetObject.invokeMethodAsync('CallbackComplexityCheck', false)
                        return message;
                    }
                    dotNetObject.invokeMethodAsync('CallbackComplexityCheck', true)
                    return 'strong';
                }
            }, 0);
            // remove red border on page load, the timer allows js to wire up before removing the class that's added by the js
            setTimeout(function () {
                passwordField.children[0].classList.remove("smart-password-short");
            }, 10);
            return true;
        }
    })(window);
    

    index.html

        
    <script src="js/complexityCheck.js"></script>
        <script src="_content/Smart.Blazor/js/smart.blazor.js"></script>
        <script src="_content/Smart.Blazor/js/smart.elements.js"></script>
    

    razor page example

    <EditForm Model="SomeModel" OnValidSubmit="ProcessMyForm">
            <DataAnnotationsValidator />
            <div class="mb-3">
                <label for="password">New Password</label>
                <template id="tooltip-password">
                    <span>{{value}}</span>
                </template>
                <PasswordTextBox Required id="password" TooltipArrow TooltipTemplate="tooltip-password" Placeholder="Enter password" @bind-Value="SomeModel.Password" ShowPasswordIcon ShowPasswordStrength Name="password"></PasswordTextBox>
                <ValidationMessage For="@(() => SomeModel.Password)" />
            </div>
            <div class="mb-3">
                <label for="confirmPassword">Confirm New Password</label>
                <PasswordTextBox Class="form-control" Required Placeholder="Confirm password" @bind-Value="SomeModel.ConfirmPassword" ShowPasswordIcon Name="confirmPassword"></PasswordTextBox>
                <ValidationMessage For="@(() => SomeModel.ConfirmPassword)" />
            </div>
            <button type="submit" id="submit" disabled="@(!isComplexityValid || loading)" class="btn btn-primary">
                @if (loading)
                {
                    <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
                    <span class="sr-only">Processing...</span>
                }
                else
                {
                    <span class="sr-only">Submit</span>
                }
            </button>
        </EditForm>
    
    <div>
        <span class="@($"smart-badge {messageCssClass}")">@message</span>
    </div>
    <br />
    @code {
    
        private string message = string.Empty;
        private bool isComplexityValid = false;
        private bool loading = false;
        private string messageCssClass = string.Empty;
    
        protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            if (firstRender)
            {
                await JSRuntime.InvokeAsync<bool>("customStrength", DotNetObjectReference.Create(this));
            }
            await base.OnAfterRenderAsync(firstRender);
        }
    
        private async Task ProcessMyForm()
        {
            loading = true;
            var result = await // call some service here !
    
            if (result.Success)
            {
                messageCssClass = "smart-badge-success";
      
            }
            else
            {
                messageCssClass = "smart-badge-danger";
            }
            loading = false;
            message = result.Message;
            StateHasChanged();
        }
    
        [JSInvokable, EditorBrowsable(EditorBrowsableState.Never)]
        public void CallbackComplexityCheck(bool valid)
        {
            if (isComplexityValid != valid)
            {
                isComplexityValid = valid;
                StateHasChanged();
            }
        }
    
    Patrick Hume
    Participant

    seams i got the cass wrong to make that work poperly –

    smart-password-text-box {
        background-clip: content-box;
        box-sizing: border-box;
    }
    
        smart-password-text-box[show-password-strength] {
            border: red solid 3px;
        }
    
            smart-password-text-box[show-password-strength] .smart-password-short {
                border: red solid 3px;
            }
    
            smart-password-text-box[show-password-strength] .smart-password-weak {
                border: #C27BA0 solid 3px;
            }
    
            smart-password-text-box[show-password-strength] .smart-password-far {
                border: orange solid 3px;
            }
    
            smart-password-text-box[show-password-strength] .smart-password-better {
                border: yellow solid 3px;
            }
    
            smart-password-text-box[show-password-strength] .smart-password-good {
                border: deepskyblue solid 3px;
            }
    
            smart-password-text-box[show-password-strength] .smart-password-strong {
                border: green solid 3px;
            }
    
        smart-password-text-box smart-tooltip .smart-tooltip-content {
            border-radius: 3px;
        }
    

    then the js file needs to be

    (function (global) {
        global.customStrength = function (dotNetObject) {
            let allowedSymbols = '<>@!#$%^&*()_+[]{}?:;|\'"\\,./~`-=';
            const passwordTextBox = document.querySelector("smart-password-text-box").messages = {
                'en': {
                    'passwordStrength': 'Password strength',
                    'short': 'Short',
                    'weak': 'complexity Week - missing art least 1 symbol, ' + allowedSymbols,
                    'far': 'complexity Fair - missing at least 1 numerical value, 0 - 9',
                    'better': 'complexity Better - missing at least 1 upper case characture, A- Z',
                    'good': 'complexity Good - missing at least 1 lower case characture, a - z',
                    'strong': 'Strong =)',
                    'showPassword': 'Show password'
                }
            };
            setTimeout(function () {
                passwordTextBox.passwordStrength = function (password, allowedSymbols) {
                    const passwordLength = password.length;
                    let message = null;
                    // debugger;
                    if (passwordLength < 7) {
                        message = 'short';
                    } else if (!new RegExp(symbols).exec(password)) {
                        message = 'weak';
                    } else if (!new RegExp(numerical).exec(password)) {
                        message = 'far';
                    } else if (!new RegExp(upperCase).exec(password)) {
                        message = 'better';
                    } else if (!new RegExp(lowerCase).exec(password)) {
                        message = 'good';
                    }
                    if (message) {
                        dotNetObject.invokeMethodAsync('CallbackComplexityCheck', false)
                        return message;
                    }
                    dotNetObject.invokeMethodAsync('CallbackComplexityCheck', true)
                    return 'strong';
                }
            }, 0);
            return true;
        }
    })(window);
    

    This will allow one to customise the message in the tooltip template whilst still applying styling the the input

    in reply to: password minimum complexity validation #103993
    Patrick Hume
    Participant

    never mind I worked it out, I was just been a total idiot and just had to take a step back, id delete this redundant post but seems I can’t …how annoying, any way please disregard the above

Viewing 4 posts - 1 through 4 (of 4 total)