Home > Software design >  blazor editcontext validate for single field
blazor editcontext validate for single field

Time:09-08

I have a blazor component and using editcontext with data annotations. I'm trying to validate on field at a time on keypress or onblur instead of validating entire form. can someone please help me with this issue:

Below is my code

<EditForm EditContext="@editContext">
  <DataAnnotationsValidator />    
  <div >
    <label >Year Of Birth: </label>
    <InputText @bind-Value="model.YearOfBirth" @onkeypress="KeyboardEventHandler" @onfocus="onFocusEvent" @onblur="onBlurEvent" />
    <ValidationMessage For="() => model.YearOfBirth" />
  </div>
  <div >
    <label > Drivers License Id:</label>
    <InputText @bind-Value="model.DriversLicenseId" @onkeypress="KeyboardEventHandler" @onfocus="onFocusEvent" @onblur="onBlurEvent" />
    <ValidationMessage For="() => model.DriversLicenseId" />
  </div>
</EditForm>

private EditContext editContext {get; set;}
private Model model = new () {};
protected override void OnInitialized()
{
  editContext = new(model);
}

CodePudding user response:

On the normal Blazor Input controls update occurs when you exit the control.

To wire them up for the oninput event, you need to extend the existing controls. I've added the UpdateOnInput parameter to control which event the update is wired to.

Here's MyInputText:

public class MyInputText : InputText
{
    [Parameter] public bool UpdateOnInput { get; set; } = false;

    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        builder.OpenElement(0, "input");
        builder.AddMultipleAttributes(1, AdditionalAttributes);
        if (!string.IsNullOrWhiteSpace(this.CssClass))
            builder.AddAttribute(2, "class", CssClass);

        builder.AddAttribute(3, "value", BindConverter.FormatValue(CurrentValue));

        if (this.UpdateOnInput)
            builder.AddAttribute(4, "oninput", EventCallback.Factory.CreateBinder<string?>(this, __value => CurrentValueAsString = __value, CurrentValueAsString));
        else
            builder.AddAttribute(5, "onchange", EventCallback.Factory.CreateBinder<string?>(this, __value => CurrentValueAsString = __value, CurrentValueAsString));

        builder.AddElementReferenceCapture(6, __inputReference => Element = __inputReference);
        builder.CloseElement();
    }
}

The original is here: enter image description here

CodePudding user response:

The following code snippet describes how you can subscribe to the OnFieldChanged event of the EditContext object and perform validation specific to a given field (EmailAddress). The OnFieldChanged event is raised when a field value changes (this happens when you navigate out of the input text box, right ?). The code simulate a call to a database to verify that the provided email does not exist in the database. If the email address do exist in the database, a validation message is displayed to let you know about this. After you type a new email address, your input passes validation, and the message is removed... If you enter the text [email protected], input validation will fail, as this is en email address that supposedly exists in the database. Copy and test:

@page "/"
@using System.ComponentModel.DataAnnotations

<EditForm EditContext="@EditContext" OnValidSubmit="HandleValidSubmit">
    <DataAnnotationsValidator />

    <div >
        <label for="name">Name: </label>
        <InputText Id="name" Class="form-control" @bind-Value="@Model.Name"></InputText>
        <ValidationMessage For="@(() => Model.Name)" />

    </div>
    <div >
        <label for="body">Text: </label>
        <InputText Id="body" Class="form-control" @bind-Value="@Model.Text"></InputText>
        <ValidationMessage For="@(() => Model.Text)" />
    </div>
    <div >
        <label for="body">Email: </label>
        <InputText Id="body" Class="form-control" @bind-Value="@Model.EmailAddress" ></InputText>
        <ValidationMessage For="@(() => Model.EmailAddress)" />
    </div>
    <p>

        <button type="submit">Save</button>

    </p>
</EditForm>

@code
    {

    private EditContext EditContext;
    private Comment Model = new Comment();
    ValidationMessageStore messages;

    protected override void OnInitialized()
    {
        EditContext = new EditContext(Model);
        EditContext.OnFieldChanged  = EditContext_OnFieldChanged;
        messages = new ValidationMessageStore(EditContext);

    }


// Note: The OnFieldChanged event is raised for each field in the model
   private async void EditContext_OnFieldChanged(object sender, 
                                        FieldChangedEventArgs e)
    {
    
        await Task.Yield();

        var propertyValue = Model.EmailAddress;

        var emailExist = await EmailExist(propertyValue);

        if (emailExist)
        {
            messages.Clear(e.FieldIdentifier);
            messages.Add(e.FieldIdentifier, "Email already exists...");
        }
        else
        {
           messages.Clear(e.FieldIdentifier);
        }
     
       EditContext.NotifyValidationStateChanged();

    }


    // Simulate a database call to verify that the provided email does not exist in the database
    private async Task<bool> EmailExist(string emailAddress)
    {
        await Task.Yield();

        if(emailAddress == "[email protected]")
            return true;

        return false;
    }

    public async Task HandleValidSubmit()
    {
        await Task.Run(() =>
        {
            Console.WriteLine("Saving...");
            Console.WriteLine(Model.Name);
            Console.WriteLine(Model.Text);
            Console.WriteLine(Model.EmailAddress);
        });
    }

    public class Comment
    {
        [Required]
        [MaxLength(10)]
        public string Name { get; set; }

        [Required]
        public string Text { get; set; }

        [Required]
        [EmailAddress]
        [DataType(DataType.EmailAddress)]
        public string EmailAddress { get; set; }
    }

}

It is not clear what validation you want to perform within the keypress event, so I will only focus on how you perform the validation, ignoring the intricacies of this event. Here's a rudimentary of validation performed in the keypress event:

void KeyHandler(KeyboardEventArgs args)
{
    // Read a key pressed at a time
    var propertyValue = args.Key;

    var fieldIdentifier = new FieldIdentifier(Model, "EmailAddress");

    // if the key "x" was pressed
    if (propertyValue == "x")
    {
        messages.Clear();
        messages.Add(fieldIdentifier, "Do not use `x` in your email 
                                                       address.");
    }
    else
    {
        messages.Clear();

    }

    EditContext.NotifyValidationStateChanged();
}

Here's a complete code snippet. Copy and text:

@page "/"
@using System.ComponentModel.DataAnnotations

<EditForm EditContext="@EditContext" OnValidSubmit="HandleValidSubmit">
    <DataAnnotationsValidator />

    <div >
        <label for="name">Name: </label>
        <InputText Id="name" Class="form-control" @bind-Value="@Model.Name"></InputText>
        <ValidationMessage For="@(() => Model.Name)" />

    </div>
    <div >
        <label for="body">Text: </label>
        <InputText Id="body" Class="form-control" @bind-Value="@Model.Text"></InputText>
        <ValidationMessage For="@(() => Model.Text)" />
    </div>
    <div >
        <label for="body">Email: </label>
        <InputText Id="body" Class="form-control" @bind-Value="@Model.EmailAddress" @onkeypress="KeyHandler"></InputText>
        <ValidationMessage For="@(() => Model.EmailAddress)" />
    </div>
    <p>

        <button type="submit">Save</button>

    </p>
</EditForm>

@code
    {

    private EditContext EditContext;
    private Comment Model = new Comment();
    ValidationMessageStore messages;

    protected override void OnInitialized()
    {
        EditContext = new EditContext(Model);
        messages = new ValidationMessageStore(EditContext);

    }

   void KeyHandler(KeyboardEventArgs args)
   {
    // Read a key pressed at a time
    var propertyValue = args.Key;

    var fieldIdentifier = new FieldIdentifier(Model, "EmailAddress");

    // if the key "x" was pressed
    if (propertyValue == "x")
    {
        messages.Clear();
        messages.Add(fieldIdentifier, "Do not use `x` in your email 
                                                       address.");
    }
    else
    {
        messages.Clear();

    }

    EditContext.NotifyValidationStateChanged();
  }
   

    public async Task HandleValidSubmit()
    {
        await Task.Run(() =>
        {
            Console.WriteLine("Saving...");
            Console.WriteLine(Model.Name);
            Console.WriteLine(Model.Text);
            Console.WriteLine(Model.EmailAddress);
        });
    }

    public class Comment
    {
        [Required]
        [MaxLength(10)]
        public string Name { get; set; }

        [Required]
        public string Text { get; set; }

        [Required]
        [EmailAddress]
        [DataType(DataType.EmailAddress)]
        public string EmailAddress { get; set; }
    }

}
  • Related