Blazor Server表单验证失败时用JS修改手风琴标题样式的问题
Blazor Server表单验证失败时修改手风琴标题样式问题
我开发的是Blazor Server应用,需求是:当表单验证失败(比如输入为空)时,将手风琴的标题改为红色。
当前代码
index.razor页面
@page "/" <style> </style> <PageTitle>Blazor Bootstrap - Home</PageTitle> <div class="test1"> <EditForm Model="@registration" OnValidSubmit="HandleFormSubmission"> <DataAnnotationsValidator /> <Accordion> <AccordionItem Title="Accordion Item #1"> <Content> <InputText id="SmtpHost" @bind-Value="@registration.SmtpHost" placeholder="SMTP Host" /> <ValidationMessage For="@(() => registration.SmtpHost)" /> </Content> </AccordionItem> </Accordion> <button type="submit">Submit</button> </EditForm> </div> @code { [Inject] protected IJSRuntime JSRuntime { get; set; } Data.Registration registration = new(); bool isValidationError = false; bool isFormSubmitted = false; bool hasRendered = false; protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { // await Task.Yield(); // await ToggleAccordionButtonError(); } } public async Task HandleFormSubmission(EditContext context) { Console.WriteLine("Form Submitted Successfully"); isValidationError = !context.Validate(); Console.WriteLine("Testing"); Console.WriteLine(isValidationError); if (isValidationError) { isFormSubmitted = true; if (hasRendered) { ToggleAccordionButtonError(); } else { StateHasChanged(); // Notify Blazor to re-render the component } } } private async Task ToggleAccordionButtonError() { try { await JSRuntime.InvokeVoidAsync("toggleAccordionButtonError"); await JSRuntime.InvokeVoidAsync("myJavaScriptFunction"); } catch (Exception ex) { Console.WriteLine($"Error invoking JavaScript function: {ex.Message}"); } } }
custom.js文件
console.log("File recognised"); function myJavaScriptFunction() { // Invoke an alert console.log("Hello from JavaScript!"); } // .test1 .accordion-button function toggleAccordionButtonError() { console.log("Hello from JavaScript!"); var elements = document.querySelectorAll('.accordion-button.collapsed'); elements.forEach(function (element) { element.style.backgroundColor = "red"; element.style.color = "white"; }); }
我确认custom.js能正常运行,但之前在HandleFormSubmission里调用JS互操作没效果,知道Blazor预渲染会限制JS调用时机,求可行的解决办法。
解决方案
方案一:用Blazor原生绑定(推荐,无需JS)
这种方式更符合Blazor组件化思想,还能避开预渲染的JS调用限制。
- 添加错误样式
在index.razor的<style>标签里加入:
.accordion-button.error { background-color: red; color: white; }
- 自定义手风琴标题模板
如果使用的Blazor Bootstrap组件支持TitleTemplate(大部分新版本都支持),直接绑定样式类:
<AccordionItem> <TitleTemplate> <span class="@(isValidationError ? "error" : "")">Accordion Item #1</span> </TitleTemplate> <Content> <InputText id="SmtpHost" @bind-Value="@registration.SmtpHost" placeholder="SMTP Host" /> <ValidationMessage For="@(() => registration.SmtpHost)" /> </Content> </AccordionItem>
- 简化表单提交逻辑
去掉冗余的判断,验证失败后Blazor会自动触发组件更新:
public async Task HandleFormSubmission(EditContext context) { isValidationError = !context.Validate(); if (isValidationError) { isFormSubmitted = true; // 无需手动调用StateHasChanged,EditContext验证会自动触发重新渲染 } else { Console.WriteLine("Form Submitted Successfully"); // 验证通过后的业务逻辑 } }
方案二:修复JS互操作逻辑(如果必须用JS)
如果坚持要用JS,需要确保在组件渲染完成后再调用,避免预渲染的限制:
- 标记需要执行JS的状态
在@code里添加一个标记变量:
bool needToggleError = false;
- 修改表单提交逻辑
public async Task HandleFormSubmission(EditContext context) { isValidationError = !context.Validate(); if (isValidationError) { isFormSubmitted = true; needToggleError = true; StateHasChanged(); // 触发组件重新渲染,之后OnAfterRenderAsync会执行 } else { Console.WriteLine("Form Submitted Successfully"); } }
- 在OnAfterRenderAsync里执行JS
protected override async Task OnAfterRenderAsync(bool firstRender) { if (needToggleError) { await ToggleAccordionButtonError(); needToggleError = false; // 重置标记,防止重复执行 } }
- 修正JS选择器
原选择器只选中折叠状态的手风琴按钮,改成选中所有目标按钮:
function toggleAccordionButtonError() { console.log("Hello from JavaScript!"); var elements = document.querySelectorAll('.test1 .accordion-button'); elements.forEach(function (element) { element.style.backgroundColor = "red"; element.style.color = "white"; }); }
内容的提问来源于stack exchange,提问作者Duane Scheepers
相关产品推荐
相关产品推荐

