OnClick does nothing on a static page
A static page has no connection to the server once it's loaded, so C# can't run on a click. Post a form or follow a link instead, or make the page interactive.
Problem
A button with OnClick does nothing on a static page: no error, no request, and the page doesn't
change. The same goes for other C# events, such as a menu item's OnClick or a tag's
OnRemove, and for code that runs when a bound value changes (ValueChanged,
@bind-Value:after).
<Button OnClick="PublishAsync">Publish</Button>Cause
C# event handlers run over an interactive page's circuit (or in WebAssembly). A static page renders once per
request and sends HTML, with nothing left on the server to call, so the button renders as a plain
<button type="button">. The API pages label these parameters Interactive only.
Fix
Pick by what the click should do:
- Change data: make it a
Submitbutton in aForm. On a static page the post runsOnValidSubmit; on an interactive page the same handler runs without a post. With several buttons, give each aNameandValue, which post with the form on a static page, and anOnClickfor interactive pages, where nothing posts. - Show something else: make it a link with
Href, carrying any choice in the query string. - React to every change: make the page interactive with
@rendermode InteractiveServer(or WebAssembly or Auto). For filters,FilterFormapplies them through the address, on a static page too.
<Form Model="Model" FormName="post" OnValidSubmit="SaveAsync">
<TextField @bind-Value="Model!.Title" />
<Button Submit Name="intent" Value="publish"
OnClick='() => _pressed = "publish"'>Publish</Button>
<Button Submit Name="intent" Value="draft"
OnClick='() => _pressed = "draft"'>Save draft</Button>
</Form>
{
[SupplyParameterFromForm(FormName = "post")]
private PostDraft? Model { get; set; }
// Static pages: the pressed button posts its Name and Value.
[SupplyParameterFromForm(FormName = "post", Name = "intent")]
private string? Intent { get; set; }
// Interactive pages don't post: OnClick says which button it was.
private string? _pressed;
protected override void OnInitialized() => Model ??= new();
private async Task SaveAsync()
{
var publish = (Intent ?? _pressed) == "publish";
await Posts.SaveAsync(Model!, publish);
}
}
Here each button posts its intent on a static page, and OnClick records it on an
interactive one:
Preview
Code
System.ComponentModel.DataAnnotations
<Form Model="Model" FormName="article" OnValidSubmit="Save" MaxWidth="36.Rem">
<TextField @bind-Value="Model!.Title" />
<TextArea @bind-Value="Model!.Body" Rows="3" />
<FormActions Justify="Justify.Start">
<Button Submit Name="intent" Value="publish" StartIcon="Lucide.Send"
OnClick='() => _pressed = "publish"'>Publish</Button>
<Button Submit Name="intent" Value="draft" Variant="ButtonVariant.Outline" Accent="Accent.Neutral"
OnClick='() => _pressed = "draft"'>Save draft</Button>
<Button Submit Name="intent" Value="discard" Variant="ButtonVariant.Ghost" Accent="Accent.Danger"
OnClick='() => _pressed = "discard"'>Discard</Button>
</FormActions>
if (_result is not null)
{
<Alert Status="Status.Success">_result</Alert>
}
</Form>
{
[SupplyParameterFromForm(FormName = "article")]
private Article? Model { get; set; }
// Static pages: the pressed button's Name=Value posts with the form.
[SupplyParameterFromForm(FormName = "article", Name = "intent")]
private string? Intent { get; set; }
// Interactive pages post nothing, so OnClick says which button it was.
private string? _pressed;
private string? _result;
protected override void OnInitialized() => Model ??= new();
private void Save() => _result = (Intent ?? _pressed) switch
{
"publish" => $"Published \"{Model!.Title}\".",
"draft" => "Saved as a draft.",
"discard" => "Discarded the changes.",
_ => null,
};
public sealed class Article
{
[Required, StringLength(80)]
public string Title { get; set; } = "What's new in alpha.12";
public string? Body { get; set; } = "OnThisPage, PrevNext and CopyButton, for docs sites.";
}
}Related
- Button: submit buttons, links and
OnClick. - Render modes: choosing a page's mode, and state on static pages.
- A form posts to [object RadioNodeList]: names to avoid for a button.