Skip to content

Commit

Permalink
Adding 'Placeholder' APIs to Combobox. (#673)
Browse files Browse the repository at this point in the history
## 🤨 Rationale

I've recently discovered that `Placeholder` is available for `Combobox`. Since the current usages of `mat-autocomplete` in SLE use placeholder text, it seemed beneficial to move forward with exposing it on our framework APIs.
  • Loading branch information
atmgrifter00 authored Aug 9, 2022
1 parent 3a51e12 commit 2b7f674
Show file tree
Hide file tree
Showing 13 changed files with 97 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
</div>
<div class="sub-container">
<div class="container-label">Combobox</div>
<nimble-combobox aria-label="Combobox" [(ngModel)]="comboboxSelectedOption" (ngModelChange)="onComboboxChange($event)" autocomplete="both">
<nimble-combobox aria-label="Combobox" [(ngModel)]="comboboxSelectedOption" (ngModelChange)="onComboboxChange($event)" autocomplete="both" placeholder="Select value...">
<nimble-list-option *ngFor="let item of comboboxItems" [ngValue]="item">{{ item ? item.first : '' }}</nimble-list-option>
</nimble-combobox>
<div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ describe('Nimble combobox', () => {
<nimble-combobox #combobox
disabled
autocomplete="inline"
error-text="error text">
error-text="error text"
placeholder="Enter value:">
</nimble-combobox>`
})
class TestHostComponent {
Expand Down Expand Up @@ -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');
Expand All @@ -114,7 +120,8 @@ describe('Nimble combobox', () => {
<nimble-combobox #combobox
[disabled]="disabled"
[autocomplete]="autocomplete"
[error-text]="errorText">
[error-text]="errorText"
[placeholder]="placeholder">
</nimble-combobox>
`
})
Expand All @@ -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<TestHostComponent>;
Expand Down Expand Up @@ -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');
Expand All @@ -181,6 +201,7 @@ describe('Nimble combobox', () => {
<nimble-combobox #combobox
[attr.disabled]="disabled"
[attr.autocomplete]="autocomplete"
[attr.placeholder]="placeholder"
[attr.error-text]="errorText">
</nimble-combobox>
`
Expand All @@ -190,6 +211,7 @@ describe('Nimble combobox', () => {
@ViewChild('combobox', { read: ElementRef }) public elementRef: ElementRef<Combobox>;
public disabled: BooleanValueOrAttribute = null;
public autocomplete: ComboboxAutocomplete | undefined = undefined;
public placeholder = 'Enter value:';
public errorText = 'initial value';
}

Expand Down Expand Up @@ -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');
Expand Down
Original file line number Diff line number Diff line change
@@ -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"
}
Original file line number Diff line number Diff line change
@@ -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"
}
Original file line number Diff line number Diff line change
@@ -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"
}
3 changes: 2 additions & 1 deletion packages/nimble-blazor/CodeAnalysisDictionary.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<Word>lang</Word>
<Word>frameless</Word>
<Word>Dropdown</Word>
<Word>Getter</Word>
</Recognized>
<DiscreteExceptions>
</DiscreteExceptions>
Expand All @@ -22,4 +23,4 @@
<CasingExceptions>
</CasingExceptions>
</Acronyms>
</Dictionary>
</Dictionary>
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
</div>
<div class="sub-container">
<div class="container-label">Combobox</div>
<NimbleCombobox AutoComplete="AutoComplete.Both">
<NimbleCombobox AutoComplete="AutoComplete.Both" Placeholder="Select value...">
<NimbleListOption>Mary</NimbleListOption>
<NimbleListOption>Sue</NimbleListOption>
<NimbleListOption>Dexter</NimbleListOption>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
disabled="@Disabled"
position="@Position.ToAttributeValue()"
autocomplete="@AutoComplete.ToAttributeValue()"
placeholder="@Placeholder"
@attributes="AdditionalAttributes">
@ChildContent
</nimble-combobox>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ public partial class NimbleCombobox : NimbleInputBase<string?>
[Parameter]
public AutoComplete? AutoComplete { get; set; }

/// <summary>
/// Gets or sets the placeholder for the combobox
/// </summary>
[Parameter]
public string? Placeholder { get; set; }

/// <summary>
/// Gets or sets the child content to be rendered inside the combobox
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Bunit;
using System;
using System.Linq.Expressions;
using Bunit;
using NimbleBlazor;
using Xunit;

Expand Down Expand Up @@ -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);
}
Expand All @@ -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()
{
Expand All @@ -52,18 +63,11 @@ public void SelectWithOption_HasListOptionMarkup()
Assert.Contains(expectedMarkup, select.Markup);
}

private IRenderedComponent<NimbleCombobox> RenderNimbleCombobox(Position position)
{
var context = new TestContext();
context.JSInterop.Mode = JSRuntimeMode.Loose;
return context.RenderComponent<NimbleCombobox>(p => p.Add(x => x.Position, position));
}

private IRenderedComponent<NimbleCombobox> RenderNimbleCombobox(AutoComplete autoComplete)
private IRenderedComponent<NimbleCombobox> RenderNimbleComboboxWithPropertySet<TProperty>(Expression<Func<NimbleCombobox, TProperty>> propertyGetter, TProperty propertyValue)
{
var context = new TestContext();
context.JSInterop.Mode = JSRuntimeMode.Loose;
return context.RenderComponent<NimbleCombobox>(p => p.Add(x => x.AutoComplete, autoComplete));
return context.RenderComponent<NimbleCombobox>(p => p.Add(propertyGetter, propertyValue));
}

private IRenderedComponent<NimbleCombobox> RenderNimbleComboboxWithOption()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface ComboboxArgs {
invalid: boolean;
errorText: string;
currentValue: string;
placeholder: string;
}

interface OptionArgs {
Expand Down Expand Up @@ -51,6 +52,7 @@ const metadata: Meta<ComboboxArgs> = {
class="${x => (x.invalid ? 'invalid' : '')}"
aria-invalid="${x => x.invalid}"
value="${x => x.currentValue}"
placeholder="${x => x.placeholder}"
>
${repeat(x => x.options, html<OptionArgs>`
<nimble-list-option ?disabled="${x => x.disabled}">${x => x.label}</nimble-list-option>
Expand Down Expand Up @@ -81,7 +83,7 @@ const metadata: Meta<ComboboxArgs> = {
autocomplete: ComboboxAutocomplete.both,
invalid: false,
errorText: 'Value is invalid',
currentValue: 'Joaquin',
placeholder: 'Select value...',
options: [
{ label: 'Mary', disabled: false },
{ label: 'Sue', disabled: false },
Expand Down

0 comments on commit 2b7f674

Please sign in to comment.