Skip to content
Open
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
24 changes: 23 additions & 1 deletion packages/main/cypress/specs/FileUploader.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,29 @@ describe("API", () => {
cy.get("[ui5-file-uploader]")
.shadow()
.find("input[type='file']")
.should("have.attr", "aria-required", "true");
.as("nativeInput")
.should("have.attr", "required");

cy.get("@nativeInput")
.should("have.attr", "aria-invalid", "false");
});

it("aria-invalid reflects value state", () => {
(["None", "Positive", "Critical", "Information"] as const).forEach(valueState => {
cy.mount(<FileUploader required valueState={valueState}></FileUploader>);

cy.get("[ui5-file-uploader]")
.shadow()
.find("input[type='file']")
.should("have.attr", "aria-invalid", "false");
});

cy.mount(<FileUploader required valueState="Negative"></FileUploader>);

cy.get("[ui5-file-uploader]")
.shadow()
.find("input[type='file']")
.should("have.attr", "aria-invalid", "true");
});

it("accept property", () => {
Expand Down
3 changes: 1 addition & 2 deletions packages/main/src/FileUploader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,7 @@ class FileUploader extends UI5Element implements IFormInputElement {
get accInfo(): InputAccInfo {
return {
"ariaRoledescription": FileUploader.i18nBundle.getText(FILEUPLOADER_ROLE_DESCRIPTION),
"ariaRequired": this.required || undefined,
"ariaInvalid": this.valueState === ValueState.Negative || undefined,
"ariaInvalid": this.valueState === ValueState.Negative,
"ariaHasPopup": "dialog",
"ariaLabel": getAllAccessibleNameRefTexts(this) || getEffectiveAriaLabelText(this) || getAssociatedLabelForTexts(this) || undefined,
"ariaDescription": getAllAccessibleDescriptionRefTexts(this) || getEffectiveAriaDescriptionText(this) || undefined,
Expand Down
2 changes: 1 addition & 1 deletion packages/main/src/FileUploaderTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ export default function FileUploaderTemplate(this: FileUploader) {
multiple={this.multiple}
accept={this.accept}
disabled={this.disabled}
required={this.required}
title={this.inputTitle}
aria-roledescription={this.accInfo.ariaRoledescription}
aria-haspopup={this.accInfo.ariaHasPopup}
aria-label={this.accInfo.ariaLabel}
aria-description={this.accInfo.ariaDescription}
aria-required={this.accInfo.ariaRequired}
aria-invalid={this.accInfo.ariaInvalid}
aria-describedby={this.accInfo.ariaDescribedBy}
onClick={this._onNativeInputClick}
Expand Down
66 changes: 62 additions & 4 deletions packages/main/test/pages/FileUploader.html
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,53 @@
<ui5-button id="btnCheckFormValidity">Check Validity</ui5-button>
</form>
</div>

<div>
<ui5-title>Form submission &amp; shadow input isolation</ui5-title>
<form id="nativeSubmitForm" action="#" method="get">
<ui5-label for="nativeFormUploader">Attachment (required):</ui5-label><br>
<ui5-file-uploader id="nativeFormUploader" name="file" style="width: 350px;" required></ui5-file-uploader>
<br><br>
<ui5-label for="nativeTextInput">Name:</ui5-label><br>
<input id="nativeTextInput" name="name" required placeholder="Enter your name" style="width: 350px; padding: 6px; font-size: 14px; box-sizing: border-box;" />
<br><br>
<button type="submit" style="padding: 6px 16px;">Submit (native)</button>
&nbsp;
<ui5-button id="btnInspectFormElements">Inspect form.elements</ui5-button>
</form>
<ui5-message-strip id="formElementsResult" hidden style="margin-top: 8px;"></ui5-message-strip>
</div>

<div>
<ui5-title>Required — AT announcement</ui5-title>
<div style="display: flex; gap: 32px; flex-wrap: wrap;">
<div>
<ui5-label for="a11yRequired">Required:</ui5-label>
<ui5-file-uploader id="a11yRequired" style="width: 300px;" required></ui5-file-uploader>
</div>
<div>
<ui5-label for="a11yNotRequired">Not required:</ui5-label>
<ui5-file-uploader id="a11yNotRequired" style="width: 300px;"></ui5-file-uploader>
</div>
</div>
</div>

<div>
<ui5-title>Required with value states</ui5-title>
<div style="display: flex; gap: 32px; flex-wrap: wrap;">
<div>
<ui5-label for="a11yNoValueState">Required, no value state:</ui5-label>
<ui5-file-uploader id="a11yNoValueState" style="width: 300px;" required></ui5-file-uploader>
</div>
<div>
<ui5-label for="a11yNegativeState">Required, Negative:</ui5-label>
<ui5-file-uploader id="a11yNegativeState" style="width: 300px;" required value-state="Negative">
<div slot="valueStateMessage">This field is required</div>
</ui5-file-uploader>
</div>
</div>
</div>

<script>
const btnCheckFormValidity = document.getElementById('btnCheckFormValidity');
const formValidationMessage = document.getElementById('formValidationMessage');
Expand All @@ -130,14 +177,25 @@
function checkFormValidity(elementId, delayed = false) {
const element = document.getElementById(elementId);
const isValid = element.checkValidity();

element.reportValidity();

// Show result
formValidationMessage.hidden = false;
formValidationMessage.innerText = `checkValidity(): ${isValid} ${delayed ? '( Delayed check )' : ''}`;
formValidationMessage.innerText = `checkValidity(): ${isValid}${delayed ? ' (after change)' : ''}`;
formValidationMessage.design = isValid ? "Positive" : "Negative";
}

document.getElementById('btnInspectFormElements').addEventListener('click', function() {
const form = document.getElementById('nativeSubmitForm');
const elements = Array.from(form.elements).map(el => {
const tag = el.tagName.toLowerCase();
const id = el.id ? `#${el.id}` : '';
const name = el.name ? `[name="${el.name}"]` : '';
return `${tag}${id}${name}`;
});
const result = document.getElementById('formElementsResult');
result.hidden = false;
result.design = "Information";
result.innerText = `form.elements (${elements.length}): ${elements.join(', ')}`;
});
</script>
</body>
</html>
Loading