Blazor - 遍历 EditForm

Blazor - iterate through EditForm

我正在 Blazor.wasm 中构建一个(静态)网站,用户可以在其中上传一些文件。然后我的意图是(在所有文件都通过一些基本检查之后)迭代地呈现一组要求用户完成的字段。只有在他们提交了所有 [Required] 信息并按提交后,才会显示下一个表单。

我在下面包含了一个最小的例子。

if (valid_files == numFiles)
    {
        for (int counter = 0; counter < num_files; counter++)
        {

            paramList.Add(new ParamsForm { });
            <EditForm Model="@paramList[counter]" OnValidSubmit="@SingleSubmit">
                <DataAnnotationsValidator />
                <ValidationSummary />
                <p>
                    Camera type <br>
                    <InputText id="cameratype" @bind-Value="@paramList[counter].CameraType" />
                </p>
                
                <button type="submit">Submit</button>
            </EditForm>

        }
        <button @onclick="HandleValidSubmit">Upload Data </button>
    }

预期的行为是在每次迭代中,onbject ParamsForm 的一个 frech 实例被添加到列表中。然后我们基于该实例创建一个表单并等待用户完成该表单。一旦他们按下 Submit 按钮,for 循环的下一阶段就会开始。提交所有数据并完成 for 循环后,应出现 Upload data 按钮并邀请用户将所有数据提交到服务器。

相反,EditForm ... 部分中的代码 none 正在完成。 IE。 - 我没有看到文本框弹出,我在那里输入的任何代码(例如 @Console.WriteLine("This should show up) 似乎没有被执行。Upload data 按钮没有出现,而是抛出一个错误抱怨index is out of range,这很奇怪,因为在 for 循环顶部的代码之后,索引不再访问任何元素。

我对 c# 和 HTML 之间的交互还很陌生,所以我想我可以理解为什么我有 不应该 工作,但我不知道我怎样才能写出有用的东西。

如有任何建议,我们将不胜感激。

Blazor的方式对我来说也有点神秘——需要一段时间来适应!我知道 Blazor 有一个 OnAfterRender 事件,这让我觉得它可能不喜欢在这样的循环中让用户输入。或者它可能将 if (valid_files == numFiles) 枚举为 false,因为当标记首次呈现时这些变量尚未初始化。

我会尝试两件事:

(1) 在循环的末尾或设置 valid_filesnumFiles 的代码之后抛出 StateHasChanged() 并查看它是否满足您的要求。

(2) 可能是这样:我不是在标记中循环,而是在 FileInput 的事件处理程序中构建整个 List<ParamsForm> paramsList,而是将计数器移动到代码块, 并将 counter++ 添加到 SingleSubmit() 方法的末尾。

已经5:00了,刚起床去吃点心就回去睡觉了。让我知道如果事情仍然不顺利,明天我会尝试一个更完整的例子。 :D

关于您的class、您从何处获取文件列表等,我没有太多信息。我建议传递完整的对象而不是单个属性。例如,我宁愿在 ParamsForm class 中使用 IBrowserFile File {get; set;} 而不是 string FileName。那样的话,如果我决定——哦,我想要这个或那个 属性——它已经在那里了。

无论如何,希望这里的内容可能有用:

@if (CurrentForm is not null)
{
    <EditForm Model="CurrentForm" OnValidSubmit="@SingleSubmit">
        <DataAnnotationsValidator />
        <ValidationSummary />
        <p>
            Camera type <br>
            <InputText id="cameratype" @bind-Value="CurrentForm.CameraType" />
        </p>
        <button type="submit">Submit</button>
    </EditForm>
    @if (IsComplete) // Don't show upload button until you're done
    {
        <button @onclick="DoUploads">Upload Data </button>
    }
    @DisplayMessage
}

@code {
    class ParamsForm { public string FileName; public string CameraType; } // Just a placeholder
    List<ParamsForm> ParamsList = new List<ParamsForm>();
    ParamsForm CurrentForm { get; set; }
    int counter = 0;

    List<string> FileNames;
    bool IsComplete = false;
    string DisplayMessage = "";

    void InitializeForms()
    {
        // I don't know your class, so just an example
        foreach (var item in FileNames)
        {
            bool IsValid = false;
            // check file validity
            if (IsValid) ParamsList.Add(new ParamsForm() { FileName = item });
        }
        if(ParamsList.Count > 0)
            CurrentForm = ParamsList[0];
    }
    void SingleSubmit()
    {
        // Do stuff with CurrentForm
        if (++counter >= ParamsList.Count) IsComplete = true;
        else CurrentForm = ParamsList[counter];
    }
    async Task DoUploads()
    {
        // Do stuff with your ParamsList
        int UploadCounter = 0;
        foreach (ParamsForm item in ParamsList){
            DisplayMessage = "Uploading " + UploadCounter + " of " + ParamsList.Count;
            StateHasChanged();
            // Do the Upload;
        }
        DisplayMessage = "Finished.";
    }
}