Search code examples
html.netblazorblazor-webassemblyblazor-client-side

Blazor - iterate through EditForm


I am building a (static) website in Blazor.wasm where the users upload some number of files. My intention is then (after all the files have passed some basic checks) to iteratively present a set of fields which the users are asked to complete. Only after they have submitted all the [Required] information and press submit will the next form show up.

I have included a minimal example below.

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>
    }

The expected behaviour is that on each iteration, a frech instance of the onbject ParamsForm is added to the list. We then create a form based of that instance and wait for the user to complete the form. Once they press the Submit button the next stage of the for loop begins. Once all the data have been submitted and the for loop is completed, the Upload data button should appear and the users are invited to submit all their data to the server.

Instead, none of the code inside the EditForm ... section is being completed. I.e. - I see no popping up of text boxes, and any code that I put in there (for example @Console.WriteLine("This should show up) does not seem to be executed. The Upload data button does not appear and instead an error is thrown complaining that the index is out of range, which is weird because after the code at the top of the for loop there are no longer any elements being accessed by an index.

I am quite new to interacting between c# and HTML, so I think I can appreciate why what I have shouldn't work, but I don't know how I can go about writing something that will work.

Any advice would be gratefully recieved.


Solution

  • I don't have much information about your class, where you are getting your file list from, and so on. I recommend passing complete objects rather than individual properties. For example, I'd rather have IBrowserFile File {get; set;} in my ParamsForm class than say string FileName. That way, if I decide-- oh, I want to get this or that property-- it's already there.

    Anyway, hope something in here might be useful:

    @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.";
        }
    }