diff --git a/src/Components/Web/src/Forms/InputBase.cs b/src/Components/Web/src/Forms/InputBase.cs
index cd8d7ee8ac50..9b2a62e39021 100644
--- a/src/Components/Web/src/Forms/InputBase.cs
+++ b/src/Components/Web/src/Forms/InputBase.cs
@@ -207,13 +207,7 @@ protected string NameAttributeValue
if (_shouldGenerateFieldNames)
{
- if (_formattedValueExpression is null && ValueExpression is not null)
- {
- _formattedValueExpression = FieldPrefix != null ? FieldPrefix.GetFieldName(ValueExpression) :
- ExpressionFormatter.FormatLambda(ValueExpression);
- }
-
- return _formattedValueExpression ?? string.Empty;
+ return GetFieldName();
}
return string.Empty;
@@ -225,7 +219,7 @@ protected string NameAttributeValue
///
///
/// If an explicit "id" is provided via , that value takes precedence.
- /// Otherwise, the id is derived from with invalid characters sanitized.
+ /// Otherwise, the id is a sanitized version of in SSR mode; generated independently in interactive mode.
///
protected string IdAttributeValue
{
@@ -236,10 +230,20 @@ protected string IdAttributeValue
return Convert.ToString(idAttributeValue, CultureInfo.InvariantCulture) ?? string.Empty;
}
- return FieldIdGenerator.SanitizeHtmlId(NameAttributeValue);
+ var fieldName = NameAttributeValue;
+ if (string.IsNullOrEmpty(fieldName))
+ {
+ fieldName = GetFieldName();
+ }
+
+ return FieldIdGenerator.SanitizeHtmlId(fieldName);
}
}
+ private string GetFieldName()
+ => _formattedValueExpression ??= FieldPrefix?.GetFieldName(ValueExpression!)
+ ?? ExpressionFormatter.FormatLambda(ValueExpression!);
+
///
public override Task SetParametersAsync(ParameterView parameters)
{
diff --git a/src/Components/Web/test/Forms/InputTextTest.cs b/src/Components/Web/test/Forms/InputTextTest.cs
index f5850029183f..695ab5da3180 100644
--- a/src/Components/Web/test/Forms/InputTextTest.cs
+++ b/src/Components/Web/test/Forms/InputTextTest.cs
@@ -63,6 +63,26 @@ public async Task ExplicitIdOverridesGenerated()
Assert.Equal("custom-id", idAttribute.AttributeValue);
}
+ [Fact]
+ public async Task RendersIdAttribute_WhenShouldUseFieldIdentifiersIsFalse_InteractiveMode()
+ {
+ // simulate interactive mode where ShouldUseFieldIdentifiers is false
+ var model = new TestModel();
+ var editContext = new EditContext(model) { ShouldUseFieldIdentifiers = false };
+ var rootComponent = new TestInputHostComponent
+ {
+ EditContext = editContext,
+ ValueExpression = () => model.StringProperty,
+ };
+
+ var componentId = await RenderAndGetInputTextComponentIdAsync(rootComponent);
+ var frames = _testRenderer.GetCurrentRenderTreeFrames(componentId);
+
+ // id should still be generated for Label/Input association to work in interactive mode
+ var idAttribute = frames.Array.Single(f => f.FrameType == RenderTreeFrameType.Attribute && f.AttributeName == "id");
+ Assert.Equal("model_StringProperty", idAttribute.AttributeValue);
+ }
+
private async Task RenderAndGetInputTextComponentIdAsync(TestInputHostComponent hostComponent)
{
var hostComponentId = _testRenderer.AssignRootComponentId(hostComponent);