Skip to content

Commit df2eb61

Browse files
authored
fix(web-components): add current-value attribute to TextInput component (#33144)
1 parent f42240c commit df2eb61

File tree

4 files changed

+115
-10
lines changed

4 files changed

+115
-10
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "add current-value attribute to text-input",
4+
"packageName": "@fluentui/web-components",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

packages/web-components/docs/api-report.md

+3
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,9 @@ export class BaseTextInput extends FASTElement {
792792
control: HTMLInputElement;
793793
// @internal
794794
controlLabel: HTMLLabelElement;
795+
currentValue: string;
796+
// @internal
797+
currentValueChanged(prev: string, next: string): void;
795798
// @internal
796799
defaultSlottedNodes: Node[];
797800
// @internal

packages/web-components/src/text-input/text-input.spec.ts

+81
Original file line numberDiff line numberDiff line change
@@ -833,4 +833,85 @@ test.describe('TextInput', () => {
833833
await expect(control).toBeFocused();
834834
});
835835
});
836+
837+
test('should reset the value to an empty string when the form is reset', async ({ page }) => {
838+
const element = page.locator('fluent-text-input');
839+
const control = element.locator('input');
840+
const reset = page.locator('button');
841+
842+
await page.setContent(/* html */ `
843+
<form id="form" action="foo">
844+
<fluent-text-input name="testinput"></fluent-text-input>
845+
<button type="reset">Reset</button>
846+
</form>
847+
`);
848+
849+
await expect(control).toHaveValue('');
850+
851+
await control.fill('hello');
852+
853+
await reset.click();
854+
855+
await expect(control).toHaveValue('');
856+
});
857+
858+
test('should change the `value` property when the `current-value` attribute changes', async ({ page }) => {
859+
const element = page.locator('fluent-text-input');
860+
861+
await page.setContent(/* html */ `
862+
<fluent-text-input></fluent-text-input>
863+
`);
864+
865+
await element.evaluate(node => {
866+
node.setAttribute('current-value', 'foo');
867+
});
868+
869+
await expect(element).toHaveJSProperty('value', 'foo');
870+
});
871+
872+
test('should change the `value` property when the `currentValue` property changes', async ({ page }) => {
873+
const element = page.locator('fluent-text-input');
874+
875+
await page.setContent(/* html */ `
876+
<fluent-text-input></fluent-text-input>
877+
`);
878+
879+
await element.evaluate((node: TextInput) => {
880+
node.currentValue = 'foo';
881+
});
882+
883+
await expect(element).toHaveJSProperty('value', 'foo');
884+
});
885+
886+
test('should set the `current-value` attribute to match the `value` property', async ({ page }) => {
887+
const element = page.locator('fluent-text-input');
888+
889+
await page.setContent(/* html */ `
890+
<fluent-text-input></fluent-text-input>
891+
`);
892+
893+
await expect(element).not.toHaveAttribute('current-value');
894+
895+
await element.evaluate((node: TextInput) => {
896+
node.value = 'foo';
897+
});
898+
899+
await expect(element).toHaveAttribute('current-value', 'foo');
900+
});
901+
902+
test('should set the `currentValue` property to match the `value` property', async ({ page }) => {
903+
const element = page.locator('fluent-text-input');
904+
905+
await page.setContent(/* html */ `
906+
<fluent-text-input></fluent-text-input>
907+
`);
908+
909+
await expect(element).toHaveJSProperty('currentValue', undefined);
910+
911+
await element.evaluate((node: TextInput) => {
912+
node.value = 'foo';
913+
});
914+
915+
await expect(element).toHaveJSProperty('currentValue', 'foo');
916+
});
836917
});

packages/web-components/src/text-input/text-input.ts

+24-10
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,27 @@ export class BaseTextInput extends FASTElement {
4444
@attr({ mode: 'boolean' })
4545
public autofocus!: boolean;
4646

47+
/**
48+
* The current value of the input.
49+
* @public
50+
* @remarks
51+
* HTML Attribute: `current-value`
52+
*/
53+
@attr({ attribute: 'current-value' })
54+
public currentValue!: string;
55+
56+
/**
57+
* Tracks the current value of the input.
58+
*
59+
* @param prev - the previous value
60+
* @param next - the next value
61+
*
62+
* @internal
63+
*/
64+
currentValueChanged(prev: string, next: string): void {
65+
this.value = next;
66+
}
67+
4768
/**
4869
* The default slotted content. This is the content that appears in the text field label.
4970
*
@@ -274,13 +295,6 @@ export class BaseTextInput extends FASTElement {
274295
@attr
275296
public type: TextInputType = TextInputType.text;
276297

277-
/**
278-
* The current value of the input.
279-
*
280-
* @internal
281-
*/
282-
private _value: string = this.initialValue;
283-
284298
/**
285299
* A reference to the internal input element.
286300
*
@@ -346,14 +360,14 @@ export class BaseTextInput extends FASTElement {
346360
*/
347361
public get value(): string {
348362
Observable.track(this, 'value');
349-
return this._value;
363+
return this.currentValue;
350364
}
351365

352366
public set value(value: string) {
353-
this._value = value;
367+
this.currentValue = value;
354368

355369
if (this.$fastController.isConnected) {
356-
this.control.value = value;
370+
this.control.value = value ?? '';
357371
this.setFormValue(value);
358372
this.setValidity();
359373
Observable.notify(this, 'value');

0 commit comments

Comments
 (0)