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.3k stars 533 forks source link

What is the correct way to use Validation with the SelectList in version 0.9.3? #1983

Closed WayneHiller closed 3 years ago

WayneHiller commented 3 years ago

What is the correct way to use Validation with the SelectList in version 0.9.3? We should add it to the documentation.

stsrki commented 3 years ago

It is used the same way as regular Select since it's just a wrapper around it. But, I just checked, and it seems it's missing SelectedValueExpression parameter so data-annotations would not work. This is a bug and I will fix it.

WayneHiller commented 3 years ago

No wonder I could not get it working lol, I am using Data Annotations.

stsrki commented 3 years ago

Sorry about that

WayneHiller commented 3 years ago

No problem, glad it was easy to find the issue.

WayneHiller commented 3 years ago

Does the Autocomplete have the same issue?

stsrki commented 3 years ago

It does, but it is a combination of TextEdit and DropDown so the validation process is a little different.

WayneHiller commented 3 years ago

I think I see the reason Autocomplete validation is not working. It contains

<Validation Validator="@(Validator ?? ValidationRule.None)">

And In Validation.cs

protected virtual Type DetermineHandlerType()
        {
            if ( HandlerType == null )
            {
                if ( Validator != null )
                {
                    return typeof( ValidatorValidationHandler );
                }
                else if ( UsePattern && hasPattern )
                {
                    return typeof( PatternValidationHandler );
                }
                else if ( EditContext != null && hasFieldIdentifier )
                {
                    return typeof( DataAnnotationValidationHandler );
                }
                else
                    throw new ArgumentNullException();
            }

            return HandlerType;
        }

Maybe if ( Validator != null ) should be if ( Validator != null && Validator != ValidationRule.None)

I am not sure that DetermineHandlerType should even throw an ArgumentNullException. Does it matter if there is a Validation element and it is not used? It makes it difficult to make generic controls where the user might or might not use validation.

stsrki commented 3 years ago

Without that part, TextEdit would pick its own validation and run it against the input text. And we don't want that. We want validation to handle the selected value.

WayneHiller commented 3 years ago

I understand that Autocomplete needs the Validation passed to TextEdit but because of how DetermineHandlerType is written it will never use DataAnnotationValidationHandler

stsrki commented 3 years ago

It will not pick the right validation for Autocomplete in this case because Autocomplete only does basic Validator validation. Data annotations are not supported. For that, I would need to add SelectedValueExpression to the Autocomplete and pass it to the Validation for use.

And then maybe add the if ( Validator != null && Validator != ValidationRule.None).

WayneHiller commented 3 years ago

That would be a better way to do it. It would seem strange to say Autocomplete has Validation but not Data Annotation Validation. Besides I need it lol. The if ( Validator != null && Validator != ValidationRule.None) change in Validation.razor.cs would help me a lot with some custom controls I am writing.

It seems Blazor does not like passing a null to Validator for some reason. Validator="null" generates an error.

WayneHiller commented 3 years ago

There seems to be another issue with Autocomplete Validation

<Autocomplete TItem="string" 
TValue="string" 
Data="@Countries" 
TextField="@((item)=>item)"  
ValueField="@((item)=>item)"
ChangeTextOnKeyPress="true"
Validator="ValidationRule.IsNotEmpty"
@bind-SelectedValue="@contact.Country">
</Autocomplete>

If I just type text into the edit and tab out the Error Message goes away but the input is still set to invalid. Note that this form also has Data Annotations Validation.

image

stsrki commented 3 years ago

Well, it is validating the selected value, and you didn't select it.

WayneHiller commented 3 years ago

Should this work or do I have it wrong?

<Validation Validator="ValidationRule.IsNotEmpty">
    <Autocomplete TItem="string"
                  TValue="string"
                  Data="@Countries"
                  TextField="@((item)=>item)"
                  ValueField="@((item)=>item)"
                  ChangeTextOnKeyPress="true"
                  @bind-SelectedValue="@contact.Country">
    </Autocomplete>
    <ValidationError />
</Validation>

When I validate I get an error;

crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Object reference not set to an instance of an object.
System.NullReferenceException: Object reference not set to an instance of an object.
   at Blazorise.Validation.OnValidatingAll(ValidatingAllEventArgs e)
   at Blazorise.Validations.TryValidateAll()
   at Blazorise.Validations.ValidateAll()
   at AbsBlazor.Client.Pages.Editing.OnSubmit() in D:\Development\AIN 2\ABS\AbsBlazor\Client\Pages\Editing.razor:line 266
   at Microsoft.AspNetCore.Components.EventCallbackWorkItem.InvokeAsync[Object](MulticastDelegate delegate, Object arg)
   at Microsoft.AspNetCore.Components.EventCallbackWorkItem.InvokeAsync(Object arg)
   at Microsoft.AspNetCore.Components.ComponentBase.Microsoft.AspNetCore.Components.IHandleEvent.HandleEventAsync(EventCallbackWorkItem callback, Object arg)
   at Microsoft.AspNetCore.Components.EventCallback.InvokeAsync(Object arg)
   at Blazorise.Button.ClickHandler()
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)
WayneHiller commented 3 years ago

Oh I see the Autocomplete has it's own Validator built in.

stsrki commented 3 years ago

Yes,

And it is working as expected. So you have some values in the Autocomplete list

  1. You type Test
  2. It gives you a filtered list
  3. You don't select anything but just navigate away
  4. At this point it is giving you an error because nothing is selected. only typed.
WayneHiller commented 3 years ago

Sorry, I thought an Autocomplete was an "optional" list of values to choose from. Are you saying that I can only validate a "selected" item? Shouldn't it be whatever is in the edit that is validated? Or is this more like a Combobox that allows a user to search items and they must select one?

stsrki commented 3 years ago

That was resolved with #1857

So no, the text will not be validated.

stsrki commented 3 years ago

Closing this because the original issue was resolved. Open new ticket for Autocomplete.

WayneHiller commented 3 years ago

With that Validation change the Autocomplete has changed to a SearchableSelectList or Combobox. It is doing more than an Autocomplete should. Auto complete should just do what it's name says, replace your typed text with text from a list.

I will clone the Autocomplete and create a new control that works how it was before you added Validation then it will work for me.

I might have some places where I do want the user to be able to search for an item and have to select one from the list, in that case Autocomplete as it is now will work great.

Thank you so must for all the help :). glad the SelectList will be fixed.