Skip to content

Remove aria-invalid when validation state changes to valid #28854

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Components/Web.JS/dist/Release/blazor.server.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion src/Components/Web.JS/dist/Release/blazor.webassembly.js

This file was deleted.

28 changes: 24 additions & 4 deletions src/Components/Web/src/Forms/InputBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,24 +226,25 @@ public override Task SetParametersAsync(ParameterView parameters)
$"{nameof(Forms.EditContext)} dynamically.");
}

SetAdditionalAttributesIfValidationFailed();
UpdateAdditionalValidationAttributes();

// For derived components, retain the usual lifecycle with OnInit/OnParametersSet/etc.
return base.SetParametersAsync(ParameterView.Empty);
}

private void OnValidateStateChanged(object? sender, ValidationStateChangedEventArgs eventArgs)
{
SetAdditionalAttributesIfValidationFailed();
UpdateAdditionalValidationAttributes();

StateHasChanged();
}

private void SetAdditionalAttributesIfValidationFailed()
private void UpdateAdditionalValidationAttributes()
{
var hasAriaInvalidAttribute = AdditionalAttributes != null && AdditionalAttributes.ContainsKey("aria-invalid");
if (EditContext.GetValidationMessages(FieldIdentifier).Any())
{
if (AdditionalAttributes != null && AdditionalAttributes.ContainsKey("aria-invalid"))
if (hasAriaInvalidAttribute)
{
// Do not overwrite the attribute value
return;
Expand All @@ -258,6 +259,25 @@ private void SetAdditionalAttributesIfValidationFailed()
// we will automatically render the `aria-invalid` attribute when the validation fails
additionalAttributes["aria-invalid"] = true;
}
else if (hasAriaInvalidAttribute)
{
// No validation errors. Need to remove `aria-invalid` if it was rendered already

if (AdditionalAttributes!.Count == 1)
{
// Only aria-invalid argument is present which we don't need any more
AdditionalAttributes = null;
}
else
{
if (ConvertToDictionary(AdditionalAttributes, out var additionalAttributes))
{
AdditionalAttributes = additionalAttributes;
}

additionalAttributes.Remove("aria-invalid");
}
}
}

/// <summary>
Expand Down
37 changes: 37 additions & 0 deletions src/Components/Web/test/Forms/InputBaseTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,43 @@ public async Task UserSpecifiedAriaValueIsNotChangedIfInvalid()
Assert.Equal("userSpecifiedValue", component.AdditionalAttributes["aria-invalid"]);
}

[Fact]
public async Task AriaAttributeRemovedWhenStateChangesToValidFromInvalid()
{
// Arrange
var model = new TestModel();
var rootComponent = new TestInputHostComponent<string, TestInputComponent<string>>
{
EditContext = new EditContext(model),
ValueExpression = () => model.StringProperty
};
var fieldIdentifier = FieldIdentifier.Create(() => model.StringProperty);
var renderer = new TestRenderer();
var messageStore = new ValidationMessageStore(rootComponent.EditContext);
messageStore.Add(fieldIdentifier, "Artificial error message");
var rootComponentId = renderer.AssignRootComponentId(rootComponent);
await renderer.RenderRootComponentAsync(rootComponentId);

// Initally, it rendered one batch and is invalid
var batch1 = renderer.Batches.Single();
var componentFrame1 = batch1.GetComponentFrames<TestInputComponent<string>>().Single();
var inputComponentId = componentFrame1.ComponentId;
var component = (TestInputComponent<string>)componentFrame1.Component;
Assert.Equal("invalid", component.CssClass);
Assert.NotNull(component.AdditionalAttributes);
Assert.True(component.AdditionalAttributes.ContainsKey("aria-invalid"));

// Act: update the field state in the EditContext and notify
messageStore.Clear(fieldIdentifier);
await renderer.Dispatcher.InvokeAsync(rootComponent.EditContext.NotifyValidationStateChanged);

// Assert: The input component rendered itself again and now has the new class
var batch2 = renderer.Batches.Skip(1).Single();
Assert.Equal(inputComponentId, batch2.DiffsByComponentId.Keys.Single());
Assert.Equal("valid", component.CssClass);
Assert.Null(component.AdditionalAttributes);
}

class TestModel
{
public string StringProperty { get; set; }
Expand Down