How to place submit button for a Blazor EditForm outside of the component
Asked Answered
A

3

23

The Blazor documentation's Form Validation example has a submit button component within the EditForm component:

    <EditForm Model="@starship" > OnValidSubmit="@HandleValidSubmit">
        <DataAnnotationsValidator />
        <ValidationSummary />
    
        <p>
            <label for="identifier">Identifier: </label>
            <InputText id="identifier" bind Value="@starship.Identifier" />
        </p>
    
        Snip....

        <button type="submit">Submit</button>

        Snip...

    </EditForm>

Is there anyway to place that submit button outside of the EditForm tags and still have it 'natively' trigger the submit for that EditForm component without resorting to using JavaScript?

i.e. for the code to look something like this:

    <!-- Want this button to submit the form in the EditForm tags-->
    <button type="submit">Submit</button>

    Snip...

    <EditForm Model="@starship" OnValidSubmit="@HandleValidSubmit">
        <DataAnnotationsValidator />
        <ValidationSummary />
    
        <p>
            <label for="identifier">Identifier: </label>
            <InputText id="identifier" bind-Value="@starship.Identifier" />
        </p>
    </EditForm>
Allonym answered 3/5, 2019 at 18:21 Comment(1)
I have blazor components on the page, I want to encapsulate the form and the validation inside of the component(s), but I have a save button at the top of the page.Percolate
D
48

It's very simple:

  • Add an id attribute to the EditForm
  • Put the submit button outside the EditForm, and assign to its form attribute the id of the EditForm.

Here's a working code sample:

    @using System.ComponentModel.DataAnnotations;    

    <EditForm id="@MyID" Model="Model" OnValidSubmit="HandleValidSubmit">
    <DataAnnotationsValidator />

    <div class="form-group">
        <label for="name">Name: </label>
        <InputText Id="name" Class="form-control" @bind-Value="@Model.Name"> 
        </InputText>
        <ValidationMessage For="@(() => Model.Name)" />

    </div>
    <div class="form-group">
        <label for="body">Text: </label>
        <InputTextArea Id="body" Class="form-control" @bind-Value="@Model.Text"> 
        </InputTextArea>
        <ValidationMessage For="@(() => Model.Text)" />
    </div>
    </EditForm>

    <p>
        <button type="submit" form="@MyID" class="btn btn-primary">Save</button>
        <button type="button" class="btn btn-light" 
                               @onclick="@Cancel">Cancel</button>
    </p>
    @code
    {
        private string MyID = "myid";

        private Comment Model = new Comment();

        public async Task HandleValidSubmit()
        {
            //  await Task.Delay(3000);

            await Task.Run(() =>
            {
                Console.WriteLine("Saving...");
                Console.WriteLine(Model.Name);
                Console.WriteLine(Model.Text);
            });

        }

        private void Cancel()
        {
            Console.WriteLine("Cancelling...");
            Console.WriteLine(Model.Name);
            Console.WriteLine(Model.Text);
        }

       public class Comment
       {
           [Required]
           [MaxLength(10)]
           public string Name { get; set; }

           [Required]
           public string Text { get; set; }

       }

    }

Hope this helps...

Determinism answered 6/5, 2020 at 11:24 Comment(2)
how about adding an 'editcontext' and check if its valid from anywhere we like ?Herman
Not sure I got you... However, you can't check if its valid from anywhere you like. This is much different than initiating the submit action outside the form boundary. However, you may embed child components embedded in the EditForm, pass to them the Model, and handle those components as though they were part of the EditForm. Note: You may post a question describing in details your issues and requirements,,,Determinism
C
3

The accepted answer has helped me, but I'd like to point out that this variable in the code section is unnecessary:

private string MyID = "myid";

You can simplify this to:

<button type="submit" form="MyID" class="btn btn-primary">Save</button>

Snip...

<EditForm id="MyID" Model="Model" OnValidSubmit="HandleValidSubmit">

There was no need for the @MyID razor syntax variable to accomplish this.

Creasy answered 25/8, 2021 at 5:37 Comment(1)
You are correct, that the variable in the given situation isn't necessary. However, it is helpful to consider using a variable to control the form attribute of the button, at least, if you want to use the same button to submit different EditForms (for example, a wizard with multiple views).Blue
D
1

If you are using Blazor Components library like 'MudBlazor' you can use EditContext from the edit form and use editContext.Validate() manually.

<MudDialog>
    <DialogContent>
        
        <EditForm EditContext="@editContext">
            <DataAnnotationsValidator/>
            <ValidationSummary/>
        </EditForm>
    </DialogContent>
    <DialogActions>
        <MudButton OnClick="Cancel">Cancel</MudButton>
        <MudButton Color="MudBlazor.Color.Primary" ButtonType="ButtonType.Submit" OnClick="Submit">Create</MudButton>
    </DialogActions>
</MudDialog>

@code {
    private EditContext editContext = default!;

    [CascadingParameter]
    MudDialogInstance MudDialog { get; set; } = default!;

    [Parameter]
    [EditorRequired]
    public ManufacturerDTO model { get; set; } = default!;

    protected override void OnInitialized()
    {
        editContext = new EditContext(model);
    }

    async Task Submit()
    {
        if (editContext!.Validate())
        {
            MudDialog.Close(DialogResult.Ok(true));
        }
    }
    void Cancel() => MudDialog.Cancel();
}
Darindaring answered 22/12, 2022 at 17:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.