Skip to content

Commit

Permalink
feat(kit): MultiSelect add ability to use native dropdown on mobile (
Browse files Browse the repository at this point in the history
  • Loading branch information
vladimirpotekhin authored Mar 27, 2023
1 parent d20b0e7 commit 35b86e0
Show file tree
Hide file tree
Showing 23 changed files with 347 additions and 24 deletions.
9 changes: 8 additions & 1 deletion projects/core/components/data-list/data-list.directive.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import {Directive} from '@angular/core';
import {Directive, Provider, Type} from '@angular/core';

@Directive({
selector: 'ng-template[tuiDataList]',
})
export class TuiDataListDirective {}

export function tuiAsDataList(useExisting: Type<TuiDataListDirective>): Provider {
return {
provide: TuiDataListDirective,
useExisting,
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<tui-multi-select
placeholder="Ignored text"
class="b-form"
[formControl]="itemControl"
[tuiTextfieldLabelOutside]="true"
[tuiTextfieldCleaner]="true"
[tuiHintContent]="'hint'"
[editable]="false"
>
Star Wars persons

<select
tuiSelect
tuiMultiSelectGroup
multiple
[items]="items"
></select>
</tui-multi-select>

<tui-multi-select
placeholder="Ignored text"
class="b-form tui-space_top-5"
[formControl]="itemGroupControl"
[tuiTextfieldLabelOutside]="true"
[editable]="false"
[disabledItemHandler]="disableHandler"
>
Star Wars persons

<select
tuiSelect
tuiMultiSelectGroup
multiple
[items]="groupItems"
[labels]="labels"
></select>
</tui-multi-select>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {Component} from '@angular/core';
import {FormControl} from '@angular/forms';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
import {TuiBooleanHandler} from '@taiga-ui/cdk';

@Component({
selector: 'tui-multi-select-example-10',
templateUrl: './index.html',
changeDetection,
encapsulation,
})
export class TuiMultiSelectExample10 {
itemControl = new FormControl();
itemGroupControl = new FormControl();

items = [
'Luke Skywalker',
'Leia Organa Solo',
'Darth Vader',
'Han Solo',
'Obi-Wan Kenobi',
'Yoda',
];

groupItems = [
['Caesar', 'Greek', 'Apple and Chicken'],
['Broccoli Cheddar', 'Chicken and Rice', 'Chicken Noodle'],
];

labels = ['Salad', 'Soup'];

disableHandler: TuiBooleanHandler<string> = item => item.startsWith('Broccoli');
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ export class ExampleTuiMultiSelectComponent extends AbstractExampleTuiControl {
HTML: import('./examples/9/index.html?raw'),
};

readonly example10: TuiDocExample = {
TypeScript: import('./examples/10/index.ts?raw'),
HTML: import('./examples/10/index.html?raw'),
};

override labelOutside = true;

readonly items = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {TuiMultiSelectExample6} from './examples/6';
import {TuiMultiSelectExample7} from './examples/7';
import {TuiMultiSelectExample8} from './examples/8';
import {TuiMultiSelectExample9} from './examples/9';
import {TuiMultiSelectExample10} from './examples/10';
import {ExampleTuiMultiSelectComponent} from './multi-select.component';

@NgModule({
Expand Down Expand Up @@ -70,6 +71,7 @@ import {ExampleTuiMultiSelectComponent} from './multi-select.component';
TuiMultiSelectExample7,
TuiMultiSelectExample8,
TuiMultiSelectExample9,
TuiMultiSelectExample10,
],
exports: [ExampleTuiMultiSelectComponent],
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@
>
<tui-multi-select-example-9></tui-multi-select-example-9>
</tui-doc-example>

<tui-doc-example
id="native-select"
heading="Native select"
[content]="example10"
>
<tui-multi-select-example-10></tui-multi-select-example-10>
</tui-doc-example>
</ng-template>

<ng-template pageTab>
Expand Down
4 changes: 4 additions & 0 deletions projects/kit/components/input-tag/input-tag.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ export class TuiInputTagComponent
@tuiDefaultProp()
placeholder = '';

@Input()
@tuiDefaultProp()
removable = true;

@Input()
@tuiDefaultProp()
disabledItemHandler: TuiBooleanHandler<TuiStringifiableItem<any> | string> =
Expand Down
3 changes: 2 additions & 1 deletion projects/kit/components/input-tag/input-tag.template.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
[disabled]="computedDisabled || disabledItemHandler(item)"
[editable]="editable && !readOnly"
[hoverable]="!readOnly"
[removable]="!readOnly"
[removable]="!readOnly && removable"
[separator]="separator"
[maxLength]="maxLength"
[size]="controller.size"
Expand Down Expand Up @@ -110,6 +110,7 @@
</div>
</tui-scrollbar>
</div>
<ng-content select="select"></ng-content>
<div
*ngIf="hasRightIcons"
class="t-icons t-icons_right"
Expand Down
4 changes: 4 additions & 0 deletions projects/kit/components/multi-select/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
export * from './hide-selected.pipe';
export * from './multi-select.component';
export * from './multi-select.directive';
export * from './multi-select.module';
export * from './multi-select-group/multi-select-group.component';
export * from './multi-select-group/multi-select-group.directive';
export * from './multi-select-options';
export * from './native-multi-select/native-multi-select';
export * from './native-multi-select/native-multi-select.component';
export * from './native-multi-select/native-multi-select-group.component';
16 changes: 15 additions & 1 deletion projects/kit/components/multi-select/multi-select.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {NgControl} from '@angular/forms';
import {
AbstractTuiMultipleControl,
EMPTY_ARRAY,
TUI_IS_MOBILE,
TuiActiveZoneDirective,
tuiArrayToggle,
tuiAsControl,
Expand Down Expand Up @@ -53,6 +54,7 @@ import {TUI_ITEMS_HANDLERS, TuiItemsHandlers} from '@taiga-ui/kit/tokens';
import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus';

import {TUI_MULTI_SELECT_OPTIONS, TuiMultiSelectOptions} from './multi-select-options';
import {AbstractTuiNativeMultiSelect} from './native-multi-select/native-multi-select';

@Component({
selector: 'tui-multi-select',
Expand All @@ -74,6 +76,9 @@ export class TuiMultiSelectComponent<T>
@ContentChild(TUI_DATA_LIST_ACCESSOR as any)
private readonly accessor?: TuiDataListAccessor<T>;

@ContentChild(AbstractTuiNativeMultiSelect, {static: true})
private readonly nativeSelect?: AbstractTuiNativeMultiSelect;

@ViewChild(TuiHostedDropdownComponent)
private readonly hostedDropdown?: TuiHostedDropdownComponent;

Expand Down Expand Up @@ -142,6 +147,8 @@ export class TuiMultiSelectComponent<T>
private readonly options: TuiMultiSelectOptions<T>,
@Inject(TUI_TEXTFIELD_WATCHED_CONTROLLER)
readonly controller: TuiTextfieldController,
@Inject(TUI_IS_MOBILE)
readonly isMobile: boolean,
) {
super(control, changeDetectorRef);
}
Expand All @@ -165,6 +172,10 @@ export class TuiMultiSelectComponent<T>
return !!this.input?.focused || !!this.hostedDropdown?.focused;
}

get nativeDropdownMode(): boolean {
return !!this.nativeSelect && this.isMobile;
}

get computedValue(): readonly T[] {
return this.computedGroup ? EMPTY_ARRAY : this.value;
}
Expand Down Expand Up @@ -254,8 +265,11 @@ export class TuiMultiSelectComponent<T>
this.updateValue(value.map(({item}) => item));
}

onValueChange(value: readonly T[]): void {
this.updateValue(value);
}

onSearch(search: string | null): void {
this.open = true;
this.updateSearch(search);
}

Expand Down
28 changes: 28 additions & 0 deletions projects/kit/components/multi-select/multi-select.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {Directive} from '@angular/core';
import {TuiBooleanHandler} from '@taiga-ui/cdk';
import {AbstractTuiTextfieldHost, tuiAsTextfieldHost} from '@taiga-ui/core';

import type {TuiMultiSelectComponent} from './multi-select.component';

@Directive({
selector: 'tui-multi-select',
providers: [tuiAsTextfieldHost(TuiMultiSelectDirective)],
})
export class TuiMultiSelectDirective extends AbstractTuiTextfieldHost<
TuiMultiSelectComponent<string>
> {
override get readOnly(): boolean {
return true;
}

disableItemHandler: TuiBooleanHandler<string> = item =>
this.host.disabledItemHandler(item);

onValueChange(_: string): void {
//
}

onSelectionChange(value: string[]): void {
this.host.onValueChange(value);
}
}
12 changes: 12 additions & 0 deletions projects/kit/components/multi-select/multi-select.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ import {
TuiWrapperModule,
} from '@taiga-ui/core';
import {TuiArrowModule} from '@taiga-ui/kit/components/arrow';
import {TuiDataListWrapperModule} from '@taiga-ui/kit/components/data-list-wrapper';
import {TuiInputTagModule} from '@taiga-ui/kit/components/input-tag';
import {TuiMultiSelectOptionModule} from '@taiga-ui/kit/components/multi-select-option';
import {PolymorpheusModule} from '@tinkoff/ng-polymorpheus';

import {TuiHideSelectedPipe} from './hide-selected.pipe';
import {TuiMultiSelectComponent} from './multi-select.component';
import {TuiMultiSelectDirective} from './multi-select.directive';
import {TuiMultiSelectGroupComponent} from './multi-select-group/multi-select-group.component';
import {TuiMultiSelectGroupDirective} from './multi-select-group/multi-select-group.directive';
import {TuiNativeMultiSelectComponent} from './native-multi-select/native-multi-select.component';
import {TuiNativeMultiSelectGroupComponent} from './native-multi-select/native-multi-select-group.component';

@NgModule({
imports: [
Expand All @@ -40,6 +44,8 @@ import {TuiMultiSelectGroupDirective} from './multi-select-group/multi-select-gr
TuiHostedDropdownModule,
TuiInputTagModule,
TuiMultiSelectOptionModule,
TuiDataListWrapperModule,
TuiMapperPipeModule,
TuiLinkModule,
TuiDataListModule,
TuiTextfieldControllerModule,
Expand All @@ -49,12 +55,18 @@ import {TuiMultiSelectGroupDirective} from './multi-select-group/multi-select-gr
TuiMultiSelectGroupComponent,
TuiMultiSelectGroupDirective,
TuiHideSelectedPipe,
TuiNativeMultiSelectComponent,
TuiNativeMultiSelectGroupComponent,
TuiMultiSelectDirective,
],
exports: [
TuiMultiSelectComponent,
TuiMultiSelectGroupComponent,
TuiMultiSelectGroupDirective,
TuiHideSelectedPipe,
TuiMultiSelectDirective,
TuiNativeMultiSelectComponent,
TuiNativeMultiSelectGroupComponent,
],
})
export class TuiMultiSelectModule {}
4 changes: 4 additions & 0 deletions projects/kit/components/multi-select/multi-select.style.less
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,8 @@
.t-arrow {
pointer-events: auto;
cursor: pointer;

&_native-dropdown {
pointer-events: none;
}
}
16 changes: 15 additions & 1 deletion projects/kit/components/multi-select/multi-select.template.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<tui-hosted-dropdown
class="t-hosted"
[canOpen]="interactive"
[canOpen]="interactive && !nativeDropdownMode"
[content]="datalist || ''"
[(open)]="open"
(tuiActiveZoneChange)="onActiveZone($event)"
Expand All @@ -21,6 +21,7 @@
[pseudoInvalid]="computedInvalid"
[editable]="false"
[expandable]="expandable"
[removable]="!nativeDropdownMode"
[search]="searchOrSpace"
[rows]="rows"
[ngModel]="computedValue | tuiMapper : valueMapper : stringify"
Expand All @@ -31,7 +32,19 @@
(click.prevent)="onClick(inputTag)"
>
<ng-content></ng-content>
<ng-template #select>
<ng-content
*ngIf="isMobile"
select="select"
></ng-content>
</ng-template>

<ng-container
*ngTemplateOutlet="select"
ngProjectAs="select"
></ng-container>
</tui-input-tag>

<div
class="t-wrapper"
[class.t-wrapper_disabled]="disabled"
Expand All @@ -54,6 +67,7 @@
automation-id="tui-multi-select__arrow"
tuiPreventDefault="mousedown"
class="t-arrow"
[class.t-arrow_native-dropdown]="nativeDropdownMode"
>
<ng-container *polymorpheusOutlet="arrow as text">
{{ text }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {ChangeDetectionStrategy, Component, Input, TemplateRef} from '@angular/core';
import {tuiAsDataList} from '@taiga-ui/core';

import {AbstractTuiNativeMultiSelect} from './native-multi-select';

@Component({
selector: 'select[multiple][tuiSelect][labels]',
templateUrl: './native-multi-select-group.template.html',
providers: [
tuiAsDataList(TuiNativeMultiSelectGroupComponent),
{
provide: TemplateRef,
deps: [TuiNativeMultiSelectGroupComponent],
useFactory: ({datalist}: TuiNativeMultiSelectGroupComponent) => datalist,
},
{
provide: AbstractTuiNativeMultiSelect,
useExisting: TuiNativeMultiSelectGroupComponent,
},
],
host: {
'[attr.aria-invalid]': 'host.invalid',
'[disabled]': 'host.disabled || control.readOnly',
'[tabIndex]': 'host.focusable ? 0 : -1',
'(change)': 'onValueChange()',
'(click.stop.silent)': '0',
'(mousedown.stop.silent)': '0',
},
styleUrls: ['./native-multi-select.style.less'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TuiNativeMultiSelectGroupComponent extends AbstractTuiNativeMultiSelect {
@Input()
items: readonly string[][] | null = [];

@Input()
labels: readonly string[] = [];
}
Loading

0 comments on commit 35b86e0

Please sign in to comment.