Megabit / Blazorise

Blazorise is a component library built on top of Blazor with support for CSS frameworks like Bootstrap, Tailwind, Bulma, AntDesign, and Material.
https://blazorise.com/
Other
3.29k stars 532 forks source link

SelectList with Validation ends with exception on Validate #2449

Closed MichalCadecky closed 3 years ago

MichalCadecky commented 3 years ago

Describe the bug I was trying to use SelectList with Validation and it seems there is a bug when validation is being performed. It always ends up with exception which can be seen in the browser console.

To Reproduce Steps to reproduce the behavior:

  1. Create new default Blazor project in Visual Studio.
  2. Create new Blazor Page with provided code.
  3. Add the page URL to navigation.
  4. Start Blazor project and navigate to new page.
  5. Either loading the page or selecting option from SelectList will throw error.

Expected behavior SelectList should work with Validation without errors.

Additional context Used razor page:

@page "/blazorise-test"

<Card>
    <CardHeader>
    </CardHeader>
    <CardBody>
        <Validations @ref="validations">
            <Validation>
                <Field>
                    <FieldLabel>Select:</FieldLabel>
                    <SelectList TItem="SelectModel"
                                TValue="int"
                                Data="@options"
                                TextField="@(item => item.Name)"
                                ValueField="@(item => item.Value)"
                                SelectedValue="@selectedOption" />
                </Field>
            </Validation>
        </Validations>
    </CardBody>
</Card>

@code {

    public class SelectModel
    {
        public string Name { get; set; }
        public int Value { get; set; }
    }

    private List<SelectModel> options = new()
    {
        new() { Name = "Option 2", Value = 2 },
        new() { Name = "Option 1", Value = 1 },
        new() { Name = "Option 3", Value = 3 },
        new() { Name = "Option 0", Value = 0 }
    };

    private int selectedOption { get; set; } = 0;

    private Validations validations;

}

Error thrown after page has been loaded:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Value cannot be null.
System.ArgumentNullException: Value cannot be null.
   at Blazorise.Validation.DetermineHandlerType()
   at Blazorise.Validation.Validate(Object newValidationValue)
   at Blazorise.Validation.InitializeInput(IValidationInput inputComponent)
   at Blazorise.BaseInputComponent`1[[System.Collections.Generic.IReadOnlyList`1[[System.Int32, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].InitializeValidation()
   at Blazorise.Select`1.<SetParametersAsync>d__3[[System.Int32, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()

Error thrown after selection has been made:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Value cannot be null.
System.ArgumentNullException: Value cannot be null.
   at Blazorise.Validation.DetermineHandlerType()
   at Blazorise.Validation.Validate(Object newValidationValue)
   at Blazorise.Validation.NotifyInputChanged[IReadOnlyList`1](IReadOnlyList`1 newExpressionValue, Boolean overrideNewValue)
   at Blazorise.BaseInputComponent`1.<CurrentValueHandler>d__8[[System.Collections.Generic.IReadOnlyList`1[[System.Int32, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)

This is very simplified version. Originally I found this issue when I was developing Blazor pages based on ABP.IO framework (AbpCrudPage with DTOs and referencing Model in Validations).

Similiar issue: #2335

stsrki commented 3 years ago

From the error, it cannot determine the validation handler. First, add a Model parameter to Validations. Then use two-way binding: @bind-SelectedValue="@selectedOption".

Also, now I noticed that I Validator parameter is missing from SelectList, I will need to add it.

MichalCadecky commented 3 years ago

Thank you! Adding Model to Validations and using @bind-SelectedValue= works but I would like to use SelectedValueChanged= handler and that is not possible with @bind-SelectedValue=. I have to change it back to SelectedValue= and doing so will end with the same errors.

stsrki commented 3 years ago

It is possible but you need to use some "secret" Blazor feature(SelectedValueExpression).

So, try this:

SelectedValue="@selectedOption" SelectedValueChanged="@OnSomething" SelectedValueExpression="@(()=>model.FieldName)"

MichalCadecky commented 3 years ago

Perfect! Finally it is working. Thanks for pointing this one out. I am closing the issue :) And thanks for the great work you are doing!