diff --git a/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html b/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html index 0d9be8005a..a5f2d039a1 100644 --- a/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html +++ b/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html @@ -105,7 +105,7 @@
Combobox
- + {{ item ? item.first : '' }}
diff --git a/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.ts b/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.ts index 2a70fb798a..29752c3a08 100644 --- a/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.ts +++ b/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.ts @@ -22,8 +22,8 @@ export class CustomAppComponent { { first: 'Mister', last: 'Smithers' } ]; - public comboboxSelectedOption = this.comboboxItems[0]; - public comboboxSelectedLastName = this.comboboxSelectedOption.last; + public comboboxSelectedOption?: ComboboxItem; + public comboboxSelectedLastName = this.comboboxSelectedOption?.last; public onMenuButtonMenuChange(event: Event): void { const menuItemText = (event.target as MenuItem).innerText; diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/nimble-combobox.directive.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/nimble-combobox.directive.ts index 24a41dce39..7c136d43ae 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/nimble-combobox.directive.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/nimble-combobox.directive.ts @@ -29,6 +29,14 @@ export class NimbleComboboxDirective { this.renderer.setProperty(this.elementRef.nativeElement, 'autocomplete', value); } + public get placeholder(): string { + return this.elementRef.nativeElement.placeholder; + } + + @Input() public set placeholder(value: string) { + this.renderer.setProperty(this.elementRef.nativeElement, 'placeholder', value); + } + public get errorText(): string | undefined { return this.elementRef.nativeElement.errorText; } diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/tests/nimble-combobox.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/tests/nimble-combobox.directive.spec.ts index dc56c3fd9f..8923b89fd4 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/tests/nimble-combobox.directive.spec.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/tests/nimble-combobox.directive.spec.ts @@ -69,7 +69,8 @@ describe('Nimble combobox', () => { + error-text="error text" + placeholder="Enter value:"> ` }) class TestHostComponent { @@ -102,6 +103,11 @@ describe('Nimble combobox', () => { expect(nativeElement.autocomplete).toEqual(ComboboxAutocomplete.inline); }); + it('will use template string values for placeholder', () => { + expect(directive.placeholder).toBe('Enter value:'); + expect(nativeElement.placeholder).toBe('Enter value:'); + }); + it('will use template string values for errorText', () => { expect(directive.errorText).toBe('error text'); expect(nativeElement.errorText).toBe('error text'); @@ -114,7 +120,8 @@ describe('Nimble combobox', () => { + [error-text]="errorText" + [placeholder]="placeholder"> ` }) @@ -124,6 +131,7 @@ describe('Nimble combobox', () => { public disabled = false; public autocomplete: ComboboxAutocomplete = ComboboxAutocomplete.list; public errorText = 'initial value'; + public placeholder = 'Enter value:'; } let fixture: ComponentFixture; @@ -163,6 +171,18 @@ describe('Nimble combobox', () => { expect(nativeElement.autocomplete).toEqual(ComboboxAutocomplete.both); }); + it('can be configured with property binding for placeholder', () => { + expect(directive.placeholder).toEqual('Enter value:'); + expect(nativeElement.placeholder).toEqual('Enter value:'); + + const newPlaceholderValue = 'Enter new value:'; + fixture.componentInstance.placeholder = newPlaceholderValue; + fixture.detectChanges(); + + expect(directive.placeholder).toEqual(newPlaceholderValue); + expect(nativeElement.placeholder).toEqual(newPlaceholderValue); + }); + it('can be configured with property binding for errorText', () => { expect(directive.errorText).toBe('initial value'); expect(nativeElement.errorText).toBe('initial value'); @@ -181,6 +201,7 @@ describe('Nimble combobox', () => { ` @@ -190,6 +211,7 @@ describe('Nimble combobox', () => { @ViewChild('combobox', { read: ElementRef }) public elementRef: ElementRef; public disabled: BooleanValueOrAttribute = null; public autocomplete: ComboboxAutocomplete | undefined = undefined; + public placeholder = 'Enter value:'; public errorText = 'initial value'; } @@ -230,6 +252,18 @@ describe('Nimble combobox', () => { expect(nativeElement.autocomplete).toEqual(ComboboxAutocomplete.both); }); + it('can be configured with attribute binding for placeholder', () => { + expect(directive.placeholder).toBe('Enter value:'); + expect(nativeElement.placeholder).toBe('Enter value:'); + + const newPlaceholderValue = 'Enter new value:'; + fixture.componentInstance.placeholder = newPlaceholderValue; + fixture.detectChanges(); + + expect(directive.placeholder).toEqual(newPlaceholderValue); + expect(nativeElement.placeholder).toEqual(newPlaceholderValue); + }); + it('can be configured with attribute binding for errorText', () => { expect(directive.errorText).toBe('initial value'); expect(nativeElement.errorText).toBe('initial value'); diff --git a/change/@ni-nimble-angular-bcfbfbd8-f4ca-4b50-84e8-3426ae747780.json b/change/@ni-nimble-angular-bcfbfbd8-f4ca-4b50-84e8-3426ae747780.json new file mode 100644 index 0000000000..728c821946 --- /dev/null +++ b/change/@ni-nimble-angular-bcfbfbd8-f4ca-4b50-84e8-3426ae747780.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Adding 'Placeholder' APIs to Combobox.", + "packageName": "@ni/nimble-angular", + "email": "26874831+atmgrifter00@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/change/@ni-nimble-blazor-1810b6fa-ca13-4127-804a-18cab9e96da2.json b/change/@ni-nimble-blazor-1810b6fa-ca13-4127-804a-18cab9e96da2.json new file mode 100644 index 0000000000..e4825b09cc --- /dev/null +++ b/change/@ni-nimble-blazor-1810b6fa-ca13-4127-804a-18cab9e96da2.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Adding 'Placeholder' APIs to Combobox.", + "packageName": "@ni/nimble-blazor", + "email": "26874831+atmgrifter00@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/change/@ni-nimble-components-9c1329ba-cc4a-4c64-a36b-c7008158a09e.json b/change/@ni-nimble-components-9c1329ba-cc4a-4c64-a36b-c7008158a09e.json new file mode 100644 index 0000000000..93e710b78e --- /dev/null +++ b/change/@ni-nimble-components-9c1329ba-cc4a-4c64-a36b-c7008158a09e.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "Adding 'Placeholder' APIs to Combobox.", + "packageName": "@ni/nimble-components", + "email": "26874831+atmgrifter00@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/nimble-blazor/CodeAnalysisDictionary.xml b/packages/nimble-blazor/CodeAnalysisDictionary.xml index fb29f00e2c..3aaed6def6 100644 --- a/packages/nimble-blazor/CodeAnalysisDictionary.xml +++ b/packages/nimble-blazor/CodeAnalysisDictionary.xml @@ -14,6 +14,7 @@ lang frameless Dropdown + Getter @@ -22,4 +23,4 @@ - \ No newline at end of file + diff --git a/packages/nimble-blazor/Examples/Demo.Shared/Pages/ComponentsDemo.razor b/packages/nimble-blazor/Examples/Demo.Shared/Pages/ComponentsDemo.razor index 40e1c22b7b..671c4edd0c 100644 --- a/packages/nimble-blazor/Examples/Demo.Shared/Pages/ComponentsDemo.razor +++ b/packages/nimble-blazor/Examples/Demo.Shared/Pages/ComponentsDemo.razor @@ -117,7 +117,7 @@
Combobox
- + Mary Sue Dexter diff --git a/packages/nimble-blazor/NimbleBlazor/Components/NimbleCombobox.razor b/packages/nimble-blazor/NimbleBlazor/Components/NimbleCombobox.razor index da80d072cd..f157c62b5e 100644 --- a/packages/nimble-blazor/NimbleBlazor/Components/NimbleCombobox.razor +++ b/packages/nimble-blazor/NimbleBlazor/Components/NimbleCombobox.razor @@ -6,6 +6,7 @@ disabled="@Disabled" position="@Position.ToAttributeValue()" autocomplete="@AutoComplete.ToAttributeValue()" + placeholder="@Placeholder" @attributes="AdditionalAttributes"> @ChildContent diff --git a/packages/nimble-blazor/NimbleBlazor/Components/NimbleCombobox.razor.cs b/packages/nimble-blazor/NimbleBlazor/Components/NimbleCombobox.razor.cs index e62b26bbb8..ccb125dbce 100644 --- a/packages/nimble-blazor/NimbleBlazor/Components/NimbleCombobox.razor.cs +++ b/packages/nimble-blazor/NimbleBlazor/Components/NimbleCombobox.razor.cs @@ -33,6 +33,12 @@ public partial class NimbleCombobox : NimbleInputBase [Parameter] public AutoComplete? AutoComplete { get; set; } + /// + /// Gets or sets the placeholder for the combobox + /// + [Parameter] + public string? Placeholder { get; set; } + /// /// Gets or sets the child content to be rendered inside the combobox /// diff --git a/packages/nimble-blazor/Tests/NimbleBlazor.Tests/Unit/Components/NimbleComboboxTests.cs b/packages/nimble-blazor/Tests/NimbleBlazor.Tests/Unit/Components/NimbleComboboxTests.cs index 77d3ab63a1..ce4adcdc0a 100644 --- a/packages/nimble-blazor/Tests/NimbleBlazor.Tests/Unit/Components/NimbleComboboxTests.cs +++ b/packages/nimble-blazor/Tests/NimbleBlazor.Tests/Unit/Components/NimbleComboboxTests.cs @@ -1,4 +1,6 @@ -using Bunit; +using System; +using System.Linq.Expressions; +using Bunit; using NimbleBlazor; using Xunit; @@ -26,7 +28,7 @@ public void NimbleCombobox_Rendered_HasSelectMarkup() [InlineData(Position.Above, "above")] public void ComboboxPosition_AttributeIsSet(Position value, string expectedAttribute) { - var select = RenderNimbleCombobox(value); + var select = RenderNimbleComboboxWithPropertySet(x => x.Position, value); Assert.Contains(expectedAttribute, select.Markup); } @@ -38,11 +40,20 @@ public void ComboboxPosition_AttributeIsSet(Position value, string expectedAttri [InlineData(AutoComplete.None, "none")] public void ComboboxAutoComplete_AttributeIsSet(AutoComplete value, string expectedAttribute) { - var select = RenderNimbleCombobox(value); + var select = RenderNimbleComboboxWithPropertySet(x => x.AutoComplete, value); Assert.Contains(expectedAttribute, select.Markup); } + [Fact] + public void ComboboxPlaceholder_AttributeIsSet() + { + var placeholder = "Select value..."; + var select = RenderNimbleComboboxWithPropertySet(x => x.Placeholder, placeholder); + + Assert.Contains("placeholder", select.Markup); + } + [Fact] public void SelectWithOption_HasListOptionMarkup() { @@ -52,18 +63,11 @@ public void SelectWithOption_HasListOptionMarkup() Assert.Contains(expectedMarkup, select.Markup); } - private IRenderedComponent RenderNimbleCombobox(Position position) - { - var context = new TestContext(); - context.JSInterop.Mode = JSRuntimeMode.Loose; - return context.RenderComponent(p => p.Add(x => x.Position, position)); - } - - private IRenderedComponent RenderNimbleCombobox(AutoComplete autoComplete) + private IRenderedComponent RenderNimbleComboboxWithPropertySet(Expression> propertyGetter, TProperty propertyValue) { var context = new TestContext(); context.JSInterop.Mode = JSRuntimeMode.Loose; - return context.RenderComponent(p => p.Add(x => x.AutoComplete, autoComplete)); + return context.RenderComponent(p => p.Add(propertyGetter, propertyValue)); } private IRenderedComponent RenderNimbleComboboxWithOption() diff --git a/packages/nimble-components/src/combobox/tests/combobox.stories.ts b/packages/nimble-components/src/combobox/tests/combobox.stories.ts index 3ae706ef61..b737ea7f7e 100644 --- a/packages/nimble-components/src/combobox/tests/combobox.stories.ts +++ b/packages/nimble-components/src/combobox/tests/combobox.stories.ts @@ -15,6 +15,7 @@ interface ComboboxArgs { invalid: boolean; errorText: string; currentValue: string; + placeholder: string; } interface OptionArgs { @@ -51,6 +52,7 @@ const metadata: Meta = { class="${x => (x.invalid ? 'invalid' : '')}" aria-invalid="${x => x.invalid}" value="${x => x.currentValue}" + placeholder="${x => x.placeholder}" > ${repeat(x => x.options, html` ${x => x.label} @@ -81,7 +83,7 @@ const metadata: Meta = { autocomplete: ComboboxAutocomplete.both, invalid: false, errorText: 'Value is invalid', - currentValue: 'Joaquin', + placeholder: 'Select value...', options: [ { label: 'Mary', disabled: false }, { label: 'Sue', disabled: false },