Blazor 모달 양식 유효성 검사 : 양식 필드를 삭제할 때 취소 단추를 두 번 클릭하여 모달을 닫아야합니다.

Jaap

Blazor에서는 CRUD에 모달 대화 상자를 사용하고 있습니다. 레코드를 편집하기 위해 모달을 열고 사용자 이름을 삭제 한 다음 (예를 들어) 취소 버튼을 직접 클릭하면 양식 유효성 검사가 계속 시작됩니다. 모달이 닫히지 않습니다.

Blazor 취소 유효성 검사 모달을 닫으려면 취소 버튼을 다시 클릭해야합니다.

취소 버튼을 외부에 둘 수 있다는 것을 알고 EditForm있지만 대화 상자가 닫히기 전에 유효성 검사 메시지가 깜박이는 것을 볼 수 있습니다. 그리고 모달 바닥 글의 제출 버튼 옆에 취소 버튼이 필요합니다.

취소 버튼을 누를 때 양식 유효성 검사를 무시할 수있는 방법이 있습니까? 그리고 JavaScript Interop을 사용하고 싶지 않습니다. 평범한 Blazor입니다.

작업 코드 예 :

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

<h3>Cancel Validation</h3>

<button type="submit" class="btn btn-primary" @onclick="Login">Login</button>
<hr />
<p>Status: @status</p>

@if (showModal)
{
    <div class="modal" tabindex="-1" role="dialog" style="display:block" id="taskModal">
        <div class="modal-dialog shadow-lg bg-white rounded" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Login</h5>
                </div>
                <div class="modal-body">
                    <EditForm Model="user" OnValidSubmit="HandleValidSubmit">
                        <DataAnnotationsValidator />
                        <ValidationSummary />
                        <div class="form-group row">
                            <label class="col-3 col-form-label">Email: </label>
                            <InputText class="col-8 form-control" @bind-Value="user.Email" />
                        </div>
                        <div class="form-group row">
                            <label class="col-3 col-form-label">Password: </label>
                            <InputText type="password" class="col-8 form-control" @bind-Value="user.Password" />
                        </div>
                        <div class="modal-footer">
                            <button type="submit" class="btn btn-primary">Submit</button>
                            <button type="button" class="btn btn-secondary" @onclick="CancelSubmit">Cancel</button>
                        </div>
                    </EditForm>
                </div>
            </div>
        </div>
    </div>
}

@code {

    public class UserLogin
    {
        [Required(ErrorMessage = "Email is required")]
        public string Email { get; set; }

        [Required(ErrorMessage = "Password is required")]
        public string Password { get; set; }
    }

    UserLogin user = new UserLogin();

    bool showModal;
    string status;

    protected override void OnInitialized()
    {
        showModal = false;
        status = "Init";
        // for demo purposes, if you delete user.Email in the login dialog, you'll need to press 'Cancel' 2 times.
        user.Email = "[email protected]";
        user.Password = "12345";
    }

    private void Login()
    {
        status = "Show Login Modal";
        showModal = true;
    }

    private void HandleValidSubmit()
    {
        status = "Valid Submit";
        showModal = false;
    }

    private void CancelSubmit()
    {
        status = "Cancelled"; 
        showModal = false;
    }
}
enet

@Jaap, 여기 Forms 유효성 검사의 내부를 기반으로하는 솔루션이 있습니다. 더 나은 솔루션이 제공 될 때까지 만족하실 수 있기를 바랍니다.

Blazor에서 EditContext 개체에 추가 된 양식 유효성 검사 지원은 개체 수준 및 필드 수준의 두 가지 수준에서 수행됩니다. 제출 버튼을 클릭하면 전체 모델이 검증됩니다. 제출 버튼이 완벽하게 잘 작동하고 모델의 필드 값이 유효하지 않으면 제출할 수 없음을 이미 확인했습니다. 취소 버튼을 누르고 모델의 필드 값이 유효하면 대화 상자가 문제없이 닫힙니다. 그러나 하나 이상의 필드에 유효하지 않은 값이있는 경우 (예 : 이메일 필드를 지운 후) 취소 버튼을 클릭하면 취소 버튼의 이벤트 핸들러에있는 코드가 가장 적기 전에 필드 수준 유효성 검사가 즉시 시작됩니다. 뭔가를 할 기회. 이 동작은 의도적으로 설계된 것이며 DataAnnotations 유효성 검사 대신 Fluent 유효성 검사를 사용한 경우에도 반복됩니다. 결론 : 시스템이 아니라 우리의 한계입니다. Blazor를 배우는 데 더 많은 시간을 투자해야합니다. 제가 제안하는 해결책은 취소 버튼을 클릭 할 때 필드 수준 유효성 검사를 비활성화하여 즉시 대화 상자를 닫는 것입니다.검증이 전혀 이루어 지지 않고 있습니다.

참고 : 내 코드는 Fluent Validation을 실험 할 때 Fluent Validation을 사용하고 있지만 DataAnnotations Validation에서도 동일하게 수행 할 수 있습니다. 두 경우 모두 코드는 거의 동일하며 Fluent Validation과는 전혀 관련이 없습니다. Chris Sainty 의 Fluent Validation 샘플 코드를 수정했습니다.

UserLogin.cs

public class UserLogin
{
    public string Email { get; set; }
    public string Password { get; set; }
}

UserLoginValidator.cs

public class UserLoginValidator : AbstractValidator<UserLogin>
    {
       public UserLoginValidator()
     {

         RuleFor(user => user.Email).NotEmpty().WithMessage("You must enter an email address");
         RuleFor(user => user.Email).EmailAddress().WithMessage("You must provide a valid email address");
         RuleFor(user => user.Password).NotEmpty().WithMessage("You must enter a password");
         RuleFor(user => user.Password).MaximumLength(50).WithMessage("Password cannot be longer than 50 characters");
    }
 }

FluentValidationValidator.cs

public class FluentValidationValidator : ComponentBase
{
    [CascadingParameter] EditContext CurrentEditContext { get; set; }
    [Parameter] public bool ShouldValidate { get; set; }

    protected override void OnInitialized()
    {
        if (CurrentEditContext == null)
        {
            throw new InvalidOperationException($"{nameof(FluentValidationValidator)} requires a cascading " +
                $"parameter of type {nameof(EditContext)}. For example, you can use {nameof(FluentValidationValidator)} " +
                $"inside an {nameof(EditForm)}.");
        }

        CurrentEditContext.AddFluentValidation(ShouldValidate);
    }
}

EditContextFluentValidationExtensions.cs

 public static class EditContextFluentValidationExtensions
{
    public static EditContext AddFluentValidation(this EditContext editContext, bool shouldValidate)
    {
        if (editContext == null)
        {
            throw new ArgumentNullException(nameof(editContext));
        }

        var messages = new ValidationMessageStore(editContext);

        editContext.OnValidationRequested +=
            (sender, eventArgs) => ValidateModel((EditContext)sender, messages);

        editContext.OnFieldChanged +=
            (sender, eventArgs) => ValidateField(editContext, messages, eventArgs.FieldIdentifier, shouldValidate);

        return editContext;
    }

    private static void ValidateModel(EditContext editContext, ValidationMessageStore messages)
    {
        var validator = GetValidatorForModel(editContext.Model);
        var validationResults = validator.Validate(editContext.Model);

        messages.Clear();
        foreach (var validationResult in validationResults.Errors)
        {
            messages.Add(editContext.Field(validationResult.PropertyName), validationResult.ErrorMessage);
        }

        editContext.NotifyValidationStateChanged();
    }

    private static void ValidateField(EditContext editContext, ValidationMessageStore messages, in FieldIdentifier fieldIdentifier, bool shouldValidate)
    {
        Console.WriteLine(fieldIdentifier.FieldName.ToString());

        if (shouldValidate)
        {
            var properties = new[] { fieldIdentifier.FieldName };
            var context = new FluentValidation.ValidationContext(fieldIdentifier.Model, new PropertyChain(), new MemberNameValidatorSelector(properties));

            var validator = GetValidatorForModel(fieldIdentifier.Model);
            var validationResults = validator.Validate(context);

            messages.Clear(fieldIdentifier);

            foreach (var validationResult in validationResults.Errors)
            {
                messages.Add(editContext.Field(validationResult.PropertyName), validationResult.ErrorMessage);
            }

            editContext.NotifyValidationStateChanged();
        }
    }

    private static IValidator GetValidatorForModel(object model)
    {
        var abstractValidatorType = typeof(AbstractValidator<>).MakeGenericType(model.GetType());
        var modelValidatorType = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(t => t.IsSubclassOf(abstractValidatorType));
        var modelValidatorInstance = (IValidator)Activator.CreateInstance(modelValidatorType);

        return modelValidatorInstance;
    }
}

Cancel.razor

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

<h3>Cancel Validation</h3>

<button type="submit" class="btn btn-primary" @onclick="Login">Login</button>
<hr />
<p>Status: @status</p>

@if (showModal)
{
    <div class="modal" tabindex="-1" role="dialog" style="display:block" id="taskModal">
        <div class="modal-dialog shadow-lg bg-white rounded" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Login</h5>
                </div>
                <div class="modal-body">
                    <EditForm Model="user" OnValidSubmit="HandleValidSubmit">
                        @*<DataAnnotationsValidator />*@
                        <FluentValidationValidator ShouldValidate="false" />
                        @*<ValidationSummary />*@
                        <div class="form-group row">
                            <label class="col-3 col-form-label">Email: </label>
                            <InputText class="col-8 form-control" @bind-Value="user.Email" />
                            <ValidationMessage For="@(() => user.Email)" />
                        </div>
                        <div class="form-group row">
                            <label class="col-3 col-form-label">Password: </label>
                            <InputText type="password" class="col-8 form-control" @bind-Value="user.Password" />
                            <ValidationMessage For="@(() => user.Password)" />
                        </div>
                        <div class="modal-footer">
                            <button type="submit" class="btn btn-primary">Submit</button>
                            <button type="button" class="btn btn-secondary" @onclick="CancelSubmit">Cancel</button>
                        </div>
                    </EditForm>
                </div>
            </div>
        </div>
    </div>
}

@code {
    UserLogin user = new UserLogin();

    bool showModal;
    string status;

    protected override void OnInitialized()
    {
        showModal = false;
        status = "Init";
        // for demo purposes, if you delete user.Email in the login dialog, you'll need to press 'Cancel' 2 times.
        user.Email = "[email protected]";
        user.Password = "12345";
    }

    private void Login()
    {
        status = "Show Login Modal";

        showModal = true;
    }

    private void HandleValidSubmit()
    {
        status = "Valid Submit";
        showModal = false;
    }

    private void CancelSubmit()
    {
        Console.WriteLine("CancelSubmit");

        status = "Cancelled";
        showModal = false;
    }
}

FluentValidationValidator 구성 요소에는 필드 수준 유효성 검사를 제거하기 위해 false로 설정 한 ShouldValidate라는 속성이 있습니다. 실행의 흐름을 따르십시오. 매우 간단합니다. 나는 문제를 해결하기 위해 거의 아무것도하지 않기 때문에 아마도 더 짧고 더 나은 방법이있을 것이라고 생각합니다. Fluent Validation 패키지를 설치해야 할 수도 있습니다 ... 행운을 빕니다 ...

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관