微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用带有自定义向导组件的 EditForm 时,验证消息不可见

如何解决使用带有自定义向导组件的 EditForm 时,验证消息不可见

我已经按照下面的教程在 Blazor Webbassembly 中创建一个简单的向导组件,到目前为止一切顺利。

https://sinclairinat0r.com/2019/12/08/creating-a-simple-wizard-component-in-blazor

但是当我尝试将向导放入如下所示的编辑表单时,我遇到了问题。

  @page "/wizarddemo"
    
    <EditForm Model="@wizardviewmodel" OnValidSubmit="@OnValidSubmit" OnInvalidSubmit="@OnInvalidSubmit">
        <DataAnnotationsValidator />
    
        <Wizard Id="DemoWizard" @ref="wizard">
            <WizardStep StepModel="firstStepModel" Name="First Step">
    
                <div class="form-group">
                    <label class="label">First name</label><span style="color:red;">*</span>
                    <InputText id="companyName" class="form-control" type="text" @bind-Value="@firstStepModel.FirstName"></InputText>
                    <ValidationMessage For="@(() => firstStepModel.FirstName)" />
                </div>
    
                <div class="form-group">
                    <label class="label">Last name</label><span style="color:red;">*</span>
                    <InputText id="companyName" class="form-control" type="text" @bind-Value="@firstStepModel.LastName"></InputText>
                    <ValidationMessage For="@(() => firstStepModel.LastName)" />
                </div>
    
            </WizardStep>
            <WizardStep StepModel="companyModel" Name="Second Step">
                <div class="form-group">
                    <label class="label"Company</label><span style="color:red;">*</span>
                    <InputText id="companyName" class="form-control" type="text" @bind-Value="@companyModel.CompanyName"></InputText>
                    <ValidationMessage For="@(() => companyModel.CompanyName)" />
                </div>
    
    
            </WizardStep>
            <WizardStep StepModel="countryModel" Name="Final Step">
                <div class="row">
                    <div class="row">
                        <div class="form-group">
                            <label class="label">Country</label><span style="color:red;">*</span>
                            <select id="country" class="form-control selectpicker" @bind="countryModel.CountryId">
                                <option value="">--select a country--</option>
                                @foreach (var country in countries)
                                {
                                    <option value="@country.Id">@country.Name</option>
                                }
                            </select>
                            <ValidationMessage For="@(() => countryModel.CountryId)" />
                        </div>
                    </div>
                </div>
            </WizardStep>
        </Wizard>
    </EditForm>

背后的代码

    public Wizard wizard;
    protected EditForm editForm;

    private FirstStepModel firstStepModel;

    private CountryModel countryModel;

    private CompanyModel companyModel;

    private Wizardviewmodel wizardviewmodel;

    private List<Country> countries = new List<Country>();

    public string StatusMessage { get; set; }

    public string StatusClass { get; set; }

    protected override async Task OnInitializedAsync()
    {
        wizardviewmodel = new Wizardviewmodel();
        wizardviewmodel.CountryModel = new CountryModel();
        wizardviewmodel.CompanyModel = new CompanyModel();
        wizardviewmodel.FirstStepModel = new FirstStepModel();

        countryModel = new CountryModel();
        companyModel = new CompanyModel();
        firstStepModel = new FirstStepModel();

        countries.Add(new Country { Id = 1,Name = "Sweden" });
        countries.Add(new Country { Id = 2,Name = "england" });

    }

    private async Task OnValidSubmit()
    {
        StatusClass = "alert-info";
        StatusMessage = DateTime.Now + " Handle valid submit";
        wizard.ActiveStep.StepCompleted = true;
    }

    private async Task OnInvalidSubmit()
    {
        StatusClass = "alert-danger";
        StatusMessage = DateTime.Now + " Handle invalid submit";
        wizard.ActiveStep.StepCompleted = false;
    }

    public class Country
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class CountryModel
    {
        [required]
        public int? CountryId { get; set; }
    }

    public class CompanyModel
    {
        [required]
        public string CompanyName { get; set; }
    }

    public class FirstStepModel
    {
        [required]
        public string FirstName { get; set; }

        [required]
        public string LastName { get; set; }
    }

    public class Wizardviewmodel
    {
        public FirstStepModel FirstStepModel { get; set; }

        public CountryModel CountryModel { get; set; }

        public CompanyModel CompanyModel { get; set; }

    }

}

问题是当我单击向导中的“下一步”按钮或当我单击 firstStepModel.FirstName 的空“InputText”并将其留空时,“ValidationMessage”组件不会触发(或可见)然后单击 firstStepModel.LastName 的“InputText”字段并在该字段旁边键入一个名称

但是,当我再次在 FirstName 的“InputText”字段内单击时,键入一个名称,然后删除名称并在 InputText 字段外单击,然后会出现 ValidationMessages。

enter image description here

其余代码如下所示。

Wizard.razor

Wizard.razor.cs

public partial class Wizard
{
    /// <summary>
    /// List of <see cref="WizardStep"/> added to the Wizard
    /// </summary>
    protected internal List<WizardStep> Steps = new List<WizardStep>();

    /// <summary>
    /// The control Id
    /// </summary>
    [Parameter]
    public string Id { get; set; }

    public Object CurrentStepModelObject { get; set; }

    /// <summary>
    /// The ChildContent container for <see cref="WizardStep"/>
    /// </summary>
    [Parameter]
    public RenderFragment ChildContent { get; set; }

    /// <summary>
    /// The Active <see cref="WizardStep"/>
    /// </summary>
    [Parameter]
    public WizardStep ActiveStep { get; set; }

    /// <summary>
    /// The Index number of the <see cref="ActiveStep"/>
    /// </summary>
    [Parameter]
    public int ActiveStepIx { get; set; }

    /// <summary>
    /// Determines whether the Wizard is in the last step
    /// </summary>

    public bool IsLastStep { get; set; }

    /// <summary>
    /// Sets the <see cref="ActiveStep"/> to the prevIoUs Index
    /// </summary>

    protected internal void GoBack()
    {
        if (ActiveStepIx > 0)
            SetActive(Steps[ActiveStepIx - 1]);
    }

    /// <summary>
    /// Sets the <see cref="ActiveStep"/> to the next Index
    /// </summary>
    protected internal void GoNext()
    {
        bool defaultValidatorSuccess = CheckValidationStatus(CurrentStepModelObject);

        if (defaultValidatorSuccess)
        {
            ActiveStep.StepCompleted = true;
        }

        if (ActiveStepIx == Steps.Count - 1 && ActiveStep.StepCompleted)
        {

            if (defaultValidatorSuccess)
            {
                ActiveStep.StatusClass = "alert-info";
                ActiveStep.StatusMessage = DateTime.Now + " Handle valid submit";
                // last step,try save to database...
            }
            else
            {
                ActiveStep.StatusClass = "alert-danger";
                ActiveStep.StatusMessage = DateTime.Now + " Handle invalid submit";
            }
        }

        if (ActiveStepIx < Steps.Count - 1 && ActiveStep.StepCompleted)
        {
            SetActive(Steps[(Steps.IndexOf(ActiveStep) + 1)]);
        }
    }


    /// <summary>
    /// 
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    private bool CheckValidationStatus(Object obj)
    {
        //if all fields is ok
        ValidationContext ctx = new ValidationContext(obj);

        List<ValidationResult> results = new List<ValidationResult>();

        bool _defaultvalidatorSuccess = Validator.TryValidateObject(obj,ctx,results);

        return _defaultvalidatorSuccess;
    }



    /// <summary>
    /// Populates the <see cref="ActiveStep"/> the Sets the passed in <see cref="WizardStep"/> instance as the
    /// </summary>
    /// <param name="step">The WizardStep</param>
    protected internal void SetActive(WizardStep step)
    {
        ActiveStep = step ?? throw new ArgumentNullException(nameof(step));

        CurrentStepModelObject = ActiveStep.StepModel;

        ActiveStepIx = StepsIndex(step);
        if (ActiveStepIx == Steps.Count - 1)
            IsLastStep = true;
        else
            IsLastStep = false;
    }

    /// <summary>
    /// Retrieves the index of the current <see cref="WizardStep"/> in the Step List
    /// </summary>
    /// <param name="step">The WizardStep</param>
    /// <returns></returns>
    public int StepsIndex(WizardStep step) => StepsIndexInternal(step);
    protected int StepsIndexInternal(WizardStep step)
    {
        if (step == null)
            throw new ArgumentNullException(nameof(step));

        return Steps.IndexOf(step);
    }
    /// <summary>
    /// Adds a <see cref="WizardStep"/> to the WizardSteps list
    /// </summary>
    /// <param name="step"></param>
    protected internal void AddStep(WizardStep step)
    {
        Steps.Add(step);
    }

    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            SetActive(Steps[0]);
            ActiveStep.StepCompleted = false;
            StateHasChanged();
        }
    }

    protected override async Task OnInitializedAsync()
    {
        CurrentStepModelObject = new object();
    }

WizardStep.razor

  @if (Parent.ActiveStep == this)
    {
        <div class="alert @StatusClass">@StatusMessage</div>
        <div id="step-@(Parent.StepsIndex(this) + 1)">
            @ChildContent
        </div>
    }

WizardStep.razor.cs

public partial class WizardStep
{
    /// <summary>
    /// The <see cref="Wizard"/> container
    /// </summary>
    [CascadingParameter]
    protected internal Wizard Parent { get; set; }

    public string StatusMessage { get; set; }

    public string StatusClass { get; set;}

    [Parameter]
    public object StepModel { get; set; }

    /// <summary>
    /// The Child Content of the current <see cref="WizardStep"/>
    /// </summary>
    [Parameter]
    public RenderFragment ChildContent { get; set; }

    /// <summary>
    /// The Name of the step
    /// </summary>
    [Parameter]
    public string Name { get; set; }

    public bool StepCompleted { get; set; }

    protected override void OnInitialized()
    {
        Parent.AddStep(this);
    }
}

有人知道代码有什么问题吗?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。