Skip to content

Commit 1511a94

Browse files
authored
Merge pull request #30 from SQ-UI/update-how-we-pass-displayName-prop-to-sq-typeahead
Update how we pass display name prop to sq typeahead
2 parents 9030f05 + 54e1671 commit 1511a94

File tree

10 files changed

+210
-140
lines changed

10 files changed

+210
-140
lines changed

docs/form-elements-module.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ In [app.component.html](https://github.com/SQ-UI/ng-sq-ui/blob/master/src/app/ap
271271

272272
```html
273273
<sq-typeahead name="typeahead"
274+
displayProp="displayName"
274275
formControlName="typeahead"
275276
[searchResults]="searchResults"
276277
(onUserInputEnd)="searchMethod($event)"
@@ -303,6 +304,8 @@ export class AppComponent {
303304
}
304305
```
305306
307+
> If you wish to pass just an array of string, you must omit the property `displayProp` in the html.
308+
306309
### Component properties:
307310
308311
- **`@Input()` name:** `string` - Name of the typeahead. If not provided, a generic name is generated, using the following pattern: `'sq-form-control' + new Date().getTime().toString()`.
@@ -327,6 +330,8 @@ export class AppComponent {
327330
328331
- **`@Input()` multiple:** `boolean` - Allow the user to choose multiple items from the search results list. Defaults to `false`.
329332
333+
- **`@Input()` displayProp:** `string` - Specify which property of the object to use as display property. If you are just passing an array of strings you must not assign a value to this property.
334+
330335
### Class properties:
331336
332337
- **queryInputControl:** `FormControl` - The model for the input where the user types in a `query`.

docs/interfaces.md

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,3 @@ interface LabelValuePair {
66
value: any;
77
}
88
```
9-
10-
```typescript
11-
interface SearchResult {
12-
displayName: string;
13-
value: any;
14-
}
15-
```

projects/ng-sq-ui/src/lib/form-elements/typeahead/typeahead.component.html

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,28 @@
1-
<div class="typeahead-wrapper"
2-
sqOutsideClickListener
3-
[listenForOutsideClick]="listenForOutsideClick"
4-
(clickOutside)="onClickOutsideComponent()">
1+
<div class="typeahead-wrapper" sqOutsideClickListener [listenForOutsideClick]="listenForOutsideClick" (clickOutside)="onClickOutsideComponent()">
52
<div class="loader" *ngIf="isLoading"></div>
63

74
<div class="input-field typeahead" [ngClass]="{'disabled': disabled}">
85
<i class="fa fa-search" aria-hidden="true"></i>
96

10-
<label class="label"
11-
for="{{controlId}}"
12-
*ngIf="controlLabel">
7+
<label class="label" for="{{controlId}}" *ngIf="controlLabel">
138
{{controlLabel}}
149
</label>
15-
<input [formControl]="queryInputControl"
16-
*ngIf="selectedItems.size === 0"
17-
type="text"
18-
id="{{controlId}}"
19-
name="{{name}}"
20-
(focus)="turnClickOutsideListenerOn()"
21-
placeholder="{{controlPlaceholder}}">
10+
<input [formControl]="queryInputControl" *ngIf="selectedItems.size === 0" type="text" id="{{controlId}}" name="{{name}}"
11+
(focus)="turnClickOutsideListenerOn()" placeholder="{{controlPlaceholder}}">
2212

2313
<div class="entered-items" *ngIf="selectedItems.size > 0">
2414
<div class="entered-item chosen-item"
2515
*ngFor="let selectedItem of selectedItems, index as itemIndex;">
26-
<div class="content">{{selectedItem.displayName}}</div>
16+
<div class="content">{{ selectedItem.label }}</div>
2717
<div class="remove" (click)="removeSearchResult(itemIndex)" *ngIf="!disabled">
2818
<i class="fa fa-times" aria-hidden="true"></i>
2919
</div>
3020
</div>
3121
</div>
3222

3323
<div class="options" [ngClass]="{'display-none': hideResults}">
34-
<div class="option"
35-
*ngFor="let result of searchResults"
36-
(click)="selectSearchResult(result)">
37-
{{result.displayName}}
24+
<div class="option" *ngFor="let result of options" (click)="selectSearchResult(result)">
25+
{{ result.label }}
3826
</div>
3927
</div>
4028
</div>

projects/ng-sq-ui/src/lib/form-elements/typeahead/typeahead.component.spec.ts

Lines changed: 65 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,32 @@ describe('TypeaheadComponent', () => {
88
let component: TypeaheadComponent;
99
let fixture: ComponentFixture<TypeaheadComponent>;
1010

11-
const testSearchResults = [{
12-
displayName: 'option1',
13-
value: {key: 1}
11+
const testSearchResults = [
12+
{
13+
label: 'option1',
14+
value: { key: 1 },
1415
},
1516
{
16-
displayName: 'option2',
17-
value: {key: 2}
17+
label: 'option2',
18+
value: { key: 2 },
1819
},
1920
{
20-
displayName: 'option3',
21-
value: {id: '1234', key: 3}
22-
}];
21+
label: 'option3',
22+
value: { id: '1234', key: 3 },
23+
},
24+
];
2325

2426
beforeEach(async(() => {
2527
TestBed.configureTestingModule({
26-
declarations: [
27-
TypeaheadComponent,
28-
OutsideClickListenerDirective
29-
],
30-
imports: [
31-
FormsModule,
32-
ReactiveFormsModule
33-
]
34-
})
35-
.compileComponents();
28+
declarations: [TypeaheadComponent, OutsideClickListenerDirective],
29+
imports: [FormsModule, ReactiveFormsModule],
30+
}).compileComponents();
3631
}));
3732

3833
beforeEach(() => {
3934
fixture = TestBed.createComponent(TypeaheadComponent);
4035
component = fixture.componentInstance;
36+
component.displayProp = '';
4137
fixture.detectChanges();
4238
});
4339

@@ -48,7 +44,10 @@ describe('TypeaheadComponent', () => {
4844
it('#should populate with search results on end of user input', () => {
4945
component.searchResults = testSearchResults;
5046

51-
expect(component.searchResults.length > 0).toBe(true, 'search results are properly populated');
47+
expect(component.searchResults.length > 0).toBe(
48+
true,
49+
'search results are properly populated',
50+
);
5251
});
5352

5453
it('#should choose one item when [multiple] = false', () => {
@@ -61,11 +60,12 @@ describe('TypeaheadComponent', () => {
6160
component.selectSearchResult(component.searchResults[0]);
6261
component.selectSearchResult(component.searchResults[1]);
6362

63+
console.log(Object.is(component.selectedItems.get(0), component.value[0]));
6464
// the typeahead should return a new array with the copied search items
65-
expect(component.value.length === 1 &&
66-
!Object.is(component.selectedItems.get(0).value, component.value[0].value) &&
67-
component.value[0].value.id === component.selectedItems.get(0).value.id)
68-
.toBe(true, 'single choice is correctly populated');
65+
expect(
66+
component.value.length === 1 &&
67+
Object.is(component.selectedItems.get(0), component.value[0]),
68+
).toBe(true, 'single choice is correctly populated');
6969
});
7070

7171
it('#should be able to choose more than one result when [multiple] = true', () => {
@@ -76,9 +76,10 @@ describe('TypeaheadComponent', () => {
7676
component.selectSearchResult(component.searchResults[i]);
7777
}
7878

79-
expect(component.value.length === testSearchResults.length &&
80-
!Object.is(component.selectedItems, component.value))
81-
.toBe(true, 'multiple choice is correctly populated');
79+
expect(
80+
component.value.length === testSearchResults.length &&
81+
!Object.is(component.selectedItems, component.value),
82+
).toBe(true, 'multiple choice is correctly populated');
8283
});
8384

8485
it('#should remove selected item by using the remove button', () => {
@@ -89,27 +90,54 @@ describe('TypeaheadComponent', () => {
8990

9091
component.removeSearchResult(component.selectedItems.size - 1);
9192

92-
expect(component.value.length === 0)
93-
.toBe(true, 'selected item successfully removed');
93+
expect(component.value.length === 0).toBe(
94+
true,
95+
'selected item successfully removed',
96+
);
9497
});
9598

96-
it('#should be able to populate correctly with a pre-defined SearchResult[] when [multiple] = true', () => {
99+
it('#should be able to populate correctly with a pre-defined LabelValuePair[] when [multiple] = true', () => {
97100
component.multiple = true;
98101
component.value = testSearchResults;
99-
expect(component.selectedItems.toArray())
100-
.toEqual(component.value, 'component value and immutable list have the same items and length');
102+
expect(component.selectedItems.toArray()).toEqual(
103+
component.value,
104+
'component value and immutable list have the same items and length',
105+
);
101106
});
102107

103-
it('#should be able to populate correctly with a pre-defined SearchResult[] when [multiple] = false', () => {
108+
it('#should be able to populate correctly with a pre-defined LabelValuePair[] when [multiple] = false', () => {
104109
component.multiple = false;
105110
component.value = testSearchResults;
106111
const itemsToArray = component.selectedItems.toArray();
107-
expect(itemsToArray.length === 1)
108-
.toBe(true, 'immutable list has only one item');
109-
110-
expect(Object.is(itemsToArray[0], component.value[0]))
111-
.toBe(true, 'the only item is the first one from the value array');
112+
expect(itemsToArray.length === 1).toBe(
113+
true,
114+
'immutable list has only one item',
115+
);
116+
117+
expect(Object.is(itemsToArray[0], component.value[0])).toBe(
118+
true,
119+
'the only item is the first one from the value array',
120+
);
112121
});
113122

123+
it('#should be working with plain strings', () => {
124+
const stringSearchResults = ['option1', 'option2', 'option3'];
125+
126+
component.displayProp = '';
127+
component.multiple = false;
128+
component.value = stringSearchResults;
129+
component.selectSearchResult(testSearchResults[0]);
130+
component.selectSearchResult(testSearchResults[1]);
114131

132+
const itemsToArray = component.selectedItems.toArray();
133+
expect(itemsToArray.length === 1).toBe(
134+
true,
135+
'immutable list has only one item',
136+
);
137+
138+
expect(itemsToArray[0] === component.value[0]).toBe(
139+
true,
140+
'the only item is the first one from the value array',
141+
);
142+
});
115143
});

0 commit comments

Comments
 (0)