Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Tested in NVDA.
-->

<ng-container *ngIf="!multiple; else chipsTemplate">
<ng-container *ngIf="(!multiple || compact); else chipsTemplate">
<div [attr.tabindex]="!disabled &&
!readonly ?
0 : null"
Expand All @@ -35,8 +35,7 @@
matRipple
class="display"
role="combobox">
<ng-container
*ngIf="itemTemplate && !multiple && value.length && displayTemplateValue; else showDefaultValue">
<ng-container *ngIf="itemTemplate && value.length && displayTemplateValue; else showDefaultValue">
<ng-container *ngTemplateOutlet="itemTemplate; context: {
$implicit: value[0]
}">
Expand All @@ -50,10 +49,16 @@
aria-hidden="true">
{{ placeholder }}:
</span>
<span class="display-value text-label-rendered">{{
value[0]
? intl.translateLabel(value[0].text)
: defaultValue }}</span>
<ng-container *ngIf="compactSummaryTemplate; else defaultSummary">
<ng-template #displayCompactSummaryTemplate
*ngTemplateOutlet="compactSummaryTemplate; context: { $implicit: value }">
</ng-template>
</ng-container>
<ng-template #defaultSummary>
<span class="display-value text-label-rendered">
{{ computeDisplayValue() }}
</span>
</ng-template>
</div>
</ng-template>
<ng-container *ngIf="!readonly">
Expand Down Expand Up @@ -153,7 +158,7 @@
</ng-container>
</ng-container>

<mat-form-field *ngIf="searchable && !multiple"
<mat-form-field *ngIf="searchable && (!multiple || compact)"
floatLabel="never">
<input #searchInput
[placeholder]="isFormControl ? '' : placeholder"
Expand Down Expand Up @@ -310,7 +315,6 @@
</mat-list-item>
</ng-template>


<ng-template #clearIcon>
<mat-icon [matTooltip]="intl.clearSelectionLabel"
(keydown.space)="removeSelection($event)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ $componentName: "ui-suggest";
&-container {
max-width: calc(100% - #{$mat-icon-size});
}

.mat-icon {
flex-shrink: 0;
}
}

.mat-chip {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class UiSuggestFixtureDirective {

clearable?: boolean;
searchable?: boolean;
compact?: boolean;
searchableCountInfo?: { count: number; message: string };
alwaysExpanded?: boolean;
disabled?: boolean;
Expand Down Expand Up @@ -1655,6 +1656,30 @@ const sharedSpecifications = (
.forEach(valueText => expect(selectedChipsInnerText.includes(valueText)).toBeTrue());
});

it('should display all selected values in compact mode', () => {
const selectedValues = faker.helpers.shuffle(component.items!).slice(0, 3);
component.value = selectedValues;
component.compact = true;
component.searchable = true;

fixture.detectChanges();

const displayContainer = fixture.debugElement.query(By.css('.display-container'));
const displayValue = displayContainer.query(By.css('.display-value'));

if (!uiSuggest.isFormControl) {
const displayTitle = displayContainer.query(By.css('.display-title'));
expect(displayTitle.nativeElement.innerText.trim()).toBe(`${component.placeholder}:`);
} else {
const displayTitle = fixture.debugElement.query(By.css('.mat-form-field-label'));
expect(displayTitle.nativeElement.innerText.trim()).toEqual(component.placeholder);
}

selectedValues
.map(value => value.text)
.forEach(valueText => expect(displayValue.nativeElement.innerText.trim()).toContain(valueText));
});

it('should have a checkbox next to each item entry', waitForAsync(async () => {
fixture.detectChanges();

Expand Down Expand Up @@ -2428,7 +2453,8 @@ describe('Component: UiSuggest', () => {
[fetchStrategy]="fetchStrategy"
[minChars]="minChars"
[drillDown]="drillDown"
[readonly]="readonly">
[readonly]="readonly"
[compact]="compact">
</ui-suggest>
`,
})
Expand Down Expand Up @@ -2509,6 +2535,7 @@ describe('Component: UiSuggest', () => {
[fetchStrategy]="fetchStrategy"
[minChars]="minChars"
[drillDown]="drillDown"
[compact]="compact"
formControlName="test">
</ui-suggest>
</mat-form-field>
Expand Down Expand Up @@ -2682,32 +2709,45 @@ describe('Component: UiSuggest', () => {

@Component({
template: `
<ui-suggest [placeholder]="placeholder"
[defaultValue]="defaultValue"
[clearable]="clearable"
[searchable]="searchable"
[enableCustomValue]="enableCustomValue"
[alwaysExpanded]="alwaysExpanded"
[headerItems]="headerItems"
[items]="items"
[value]="value"
[direction]="direction"
[displayPriority]="displayPriority"
[disabled]="disabled"
[multiple]="multiple"
[readonly]="readonly"
[fetchStrategy]="fetchStrategy"
[displayTemplateValue]="displayTemplateValue"
[searchableCountInfo]="searchableCountInfo"
[minChars]="minChars"
[drillDown]="drillDown">
<ng-template let-item >
<div class="item-template">{{ item.text }}</div>
</ng-template>
<ui-suggest
[placeholder]="placeholder"
[defaultValue]="defaultValue"
[clearable]="clearable"
[searchable]="searchable"
[enableCustomValue]="enableCustomValue"
[alwaysExpanded]="alwaysExpanded"
[headerItems]="headerItems"
[items]="items"
[value]="value"
[direction]="direction"
[displayPriority]="displayPriority"
[disabled]="disabled"
[multiple]="multiple"
[readonly]="readonly"
[fetchStrategy]="fetchStrategy"
[displayTemplateValue]="displayTemplateValue"
[searchableCountInfo]="searchableCountInfo"
[minChars]="minChars"
[drillDown]="drillDown"
[compact]="compact"
[compactSummaryTemplate]="compactSummaryTemplate"
>
<ng-template let-item>
<div class="item-template">{{ item.text }}</div>
</ng-template>
</ui-suggest>
<ng-template #compactSummaryTemplate let-value>
<div class="custom-display-value">
<span class="text-ellipsis">{{value?.[0]?.text}}</span>
<span *ngIf="(value?.length || 0) > 1">
(+{{ (value?.length || 0) - 1 }}
{{ value?.length === 2 ? "other" : "others" }})
</span>
</div>
</ng-template>
`,
})
class UiSuggestCustomTemplateFixtureComponent extends UiSuggestFixtureDirective { }
class UiSuggestCustomTemplateFixtureComponent extends UiSuggestFixtureDirective {}

describe('Type: custom template', () => {
let fixture: ComponentFixture<UiSuggestCustomTemplateFixtureComponent>;
Expand Down Expand Up @@ -2762,6 +2802,25 @@ describe('Component: UiSuggest', () => {
});
}));

it('should render the compact summary using the provided custom template', () => {
component.items = generateSuggetionItemList('random');

const selectedValues = faker.helpers.shuffle(component.items!).slice(0, 3);
component.value = selectedValues;

component.multiple = true;
component.compact = true;
component.searchable = true;

fixture.detectChanges();

const displayContainer = fixture.debugElement.query(By.css('.display-container'));
const displayValue = displayContainer.query(By.css('.custom-display-value'));
const summaryText = displayValue.nativeElement.innerText.trim();

expect(summaryText).toBe(`${selectedValues[0].text} (+2 others)`);
});

[false, true].forEach((multiple) => {
[false, true].forEach((displayTemplateValue) => {
it(`should ${!multiple && displayTemplateValue ? '' : 'NOT'} render the displayed value with custom` +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ export class UiSuggestComponent extends UiSuggestMatFormFieldDirective
!this.isOpen &&
this._hasValue
) {
return this.value.map(v => this.intl.translateLabel(v.text)).join(', ');
return this._getValueSummary();
}

return null;
Expand Down Expand Up @@ -506,6 +506,20 @@ export class UiSuggestComponent extends UiSuggestMatFormFieldDirective
@Input()
disableTooltip = false;

/**
* Use compact summary info instead of chips
*
*/
@Input()
compact = false;

/**
* The template to use for compact summary
*
*/
@Input()
compactSummaryTemplate?: TemplateRef<any>;

/**
* Emits `once` when `data` is retrieved for the `first time`.
*
Expand Down Expand Up @@ -1105,6 +1119,12 @@ export class UiSuggestComponent extends UiSuggestMatFormFieldDirective
}
}

computeDisplayValue() {
return this.value.length > 0
? this._getValueSummary()
: this.defaultValue;
}

private _selectActiveItem(closeAfterSelect: boolean) {
const item = this.headerItems![this.activeIndex] ?? this.items[this.activeIndex - this.headerItems!.length];
if (!item) { return; }
Expand Down Expand Up @@ -1385,4 +1405,8 @@ export class UiSuggestComponent extends UiSuggestMatFormFieldDirective
if (scenario) { throw new Error(errorText); }
});
}

private _getValueSummary() {
return this.value.map(v => this.intl.translateLabel(v.text)).join(', ');
}
}
34 changes: 34 additions & 0 deletions projects/playground/src/app/pages/suggest/suggest.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,37 @@ <h2>Multiple select suggest</h2>
[searchSourceFactory]="searchSourceFactory">
</ui-suggest>
</mat-form-field>

<h2>Multiple select with compact summary instead of chips</h2>
<h3>With the default template</h3>
<mat-form-field>
<ui-suggest [searchable]="true"
[disabled]="false"
[multiple]="true"
[enableCustomValue]="true"
[searchSourceFactory]="searchSourceFactory"
[compact]="true">
</ui-suggest>
</mat-form-field>
<h3>With custom template</h3>
<mat-form-field>
<ui-suggest [searchable]="true"
[disabled]="false"
[multiple]="true"
[enableCustomValue]="true"
[searchSourceFactory]="searchSourceFactory"
[compact]="true"
[compactSummaryTemplate]="compactSummaryTemplate">
</ui-suggest>

<ng-template #compactSummaryTemplate
let-value>
<div class="flex">
<span class="text-ellipsis">{{value?.[0]?.text}}</span>
<span *ngIf="(value?.length || 0) > 1"
class="example-additional-selection">
(+{{(value?.length || 0) - 1}} {{value?.length === 2 ? 'other' : 'others'}})
</span>
</div>
</ng-template>
</mat-form-field>