Skip to content

Commit

Permalink
feat(SelectionList): now can disable user input
Browse files Browse the repository at this point in the history
This emulates a more standard dropdown experience
  • Loading branch information
benjamincharity committed Jan 10, 2020
1 parent d3028a9 commit 2fd2c4b
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 78 deletions.
4 changes: 3 additions & 1 deletion demo/app/components/selection-list/data.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { TsOption } from '@terminus/ui/option';

export interface State {

export interface State extends TsOption {
name: string;
abbreviation: string;
}
Expand Down
22 changes: 20 additions & 2 deletions demo/app/components/selection-list/selection-list.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ <h3 tsCardTitle tsVerticalSpacing>
<br>
<label>
Disable
<input type="checkbox" [(ngModel)]="isDisabled">
<input type="checkbox" [(ngModel)]="isDisabledMulti" [ngModelOptions]="{standalone: true}">
</label>
<br>
<label>
Allow user input
<input type="checkbox" [(ngModel)]="allowInputMulti" [ngModelOptions]="{standalone: true}">
</label>
</div>

Expand All @@ -25,9 +30,10 @@ <h3 tsCardTitle tsVerticalSpacing>
<ts-selection-list
label="Select states"
hint="Begin typing to search.."
[isDisabled]="isDisabled"
[isDisabled]="isDisabledMulti"
[formControl]="complexMultipleControl"
[allowMultiple]="true"
[allowUserInput]="allowInputMulti"
[reopenAfterSelection]="true"
[showProgress]="complexMultipleAsync"
[displayFormatter]="formatter"
Expand Down Expand Up @@ -70,11 +76,23 @@ <h3 tsCardTitle tsVerticalSpacing="small--1">
<button (click)="seedSelections(simpleControl, [states[0]])" tabindex="-1">
Seed selection
</button>
<br>
<label>
Disable
<input type="checkbox" [(ngModel)]="isDisabledSingle" [ngModelOptions]="{standalone: true}">
</label>
<br>
<label>
Allow user input
<input type="checkbox" [(ngModel)]="allowInputSingle" [ngModelOptions]="{standalone: true}">
</label>
</div>

<ts-selection-list
label="Select states"
hint="Begin typing to search.."
[allowUserInput]="allowInputSingle"
[isDisabled]="isDisabledSingle"
[formControl]="simpleControl"
[showProgress]="simpleAsync"
[displayFormatter]="formatter"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ export type DEMOS
templateUrl: './selection-list.component.html',
})
export class SelectionListComponent implements OnInit, OnDestroy {
public isDisabled = false;
public isDisabledMulti = false;
public isDisabledSingle = false;
public allowInputMulti = true;
public allowInputSingle = false;

// Data
public states = STATES.slice();
Expand Down
3 changes: 2 additions & 1 deletion terminus-ui/form-field/src/form-field.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@
color: var(--formField-outlineColor-disabled);
}

.c-input__text {
.c-input__text,
.ts-selection-list__input {
color: var(--formField-color-disabled);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ let nextUniqueId = 0;
// a little earlier. This avoids issues where IE delays the focusing of the input.
'(blur)': 'onTouched()',
'(focusin)': 'handleFocus()',
'(click)': 'handleFocus()',
'(input)': 'handleInput($event)',
'(keydown)': 'handleKeydown($event)',
},
Expand Down Expand Up @@ -587,7 +588,15 @@ export class TsSelectionListTriggerDirective<ValueType = string> implements Cont
*/
private canOpen(): boolean {
const element = this.elementRef.nativeElement;
return !element.readOnly && !element.disabled && !this.selectionListDisabled;
const isDisabled = coerceBooleanProperty(element.disabled)
|| coerceBooleanProperty(element.getAttribute('data-disabled'))
|| coerceBooleanProperty(this.selectionListDisabled);
const isReadOnly = coerceBooleanProperty(element.readOnly);
const allowsUserInput = coerceBooleanProperty(element.getAttribute('data-user-input'));
if (allowsUserInput) {
return !isReadOnly && !isDisabled;
}
return !isDisabled;
}


Expand Down
38 changes: 32 additions & 6 deletions terminus-ui/selection-list/src/selection-list.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
</ts-label>

<div class="ts-selection-list__input-wrap">

<ng-container *ngIf="allowMultiple">
<ts-chip-collection (tabUpdateFocus)="focusInput()">
<ts-chip-collection
(tabUpdateFocus)="focusInput()"
>
<ts-chip
*ngFor="let chip of ngControl.value; trackBy: trackByFn"
[value]="chip"
Expand All @@ -27,17 +28,21 @@

<input
class="ts-selection-list__input"
*ngIf="allowUserInput"
[tsSelectionListTrigger]="auto"
[attr.data-allow-input]="allowUserInput"
[attr.id]="id"
[disabled]="isDisabled"
[allowMultiple]="allowMultiple"
[reopenAfterSelection]="reopenAfterSelection"
[attr.id]="id"
[(ngModel)]="searchQuery"
[readonly]="isDisabled ? 'true' : null"
[readonly]="isDisabled || !allowUserInput ? 'true' : null"
(ngModelChange)="querySubject.next($event)"
(blur)="handleInputBlur($event)"
onfocus="this.select()"
#input
/>
<ng-template *ngTemplateOutlet="triggerTemplate"></ng-template>
</ts-chip-collection>

<ng-template *ngTemplateOutlet="spinnerTemplate"></ng-template>
Expand All @@ -46,10 +51,13 @@
<ng-container *ngIf="!allowMultiple">
<input
class="ts-selection-list__input"
*ngIf="allowUserInput"
[tsSelectionListTrigger]="auto"
[allowMultiple]="allowMultiple"
[attr.data-allow-input]="allowUserInput"
[attr.id]="id"
[readonly]="isDisabled ? 'true' : null"
[disabled]="isDisabled"
[allowMultiple]="allowMultiple"
[readonly]="isDisabled || !allowUserInput ? 'true' : null"
[(ngModel)]="searchQuery"
[value]="searchQuery"
(ngModelChange)="querySubject.next($event)"
Expand All @@ -58,11 +66,28 @@
#input
/>

<ng-template *ngTemplateOutlet="triggerTemplate"></ng-template>
<ng-template *ngTemplateOutlet="spinnerTemplate"></ng-template>
</ng-container>

<ts-icon *ngIf="shouldShowDropdownIcon">arrow_drop_down</ts-icon>
</div>

<!-- NOTE: This template must remain inside the form field component or disabled states aren't reflected correctly. -->
<ng-template #triggerTemplate>
<input
type="text"
fxFlex
*ngIf="!allowUserInput"
[tsSelectionListTrigger]="auto"
class="ts-selection-list__input ts-selection-list__custom-trigger"
[attr.data-disabled]="isDisabled"
readonly
value="{{ staticTriggerDisplay }}"
title="{{ staticTriggerDisplay }}"
#input
>
</ng-template>
</ts-form-field>


Expand All @@ -80,6 +105,7 @@
</ts-selection-list-panel>



<ng-template #contentTemplate>
<ng-content></ng-content>
</ng-template>
Expand Down
16 changes: 15 additions & 1 deletion terminus-ui/selection-list/src/selection-list.component.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<h1>SelectionList</h1>


<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**
Expand All @@ -12,6 +11,7 @@
- [Minimum Characters](#minimum-characters)
- [Formatting](#formatting)
- [Complex comparator](#complex-comparator)
- [Standard dropdown mode (no typing)](#standard-dropdown-mode-no-typing)
- [Events](#events)
- [Test Helpers](#test-helpers)

Expand Down Expand Up @@ -133,6 +133,20 @@ import { TsSelectionListComparator } from '@terminus/ui/selection-list';
public compareFunc: TsSelectionListComparator = (a, b) => a.id === b.id;
```

### Standard dropdown mode (no typing)

If the component should act as a standard dropdown with no ability to type a query, set the flag `allowUserInput` to
`false`. By default it is `true`.

```html
<ts-selection-list
[formControl]="myCtrl"
[allowUserInput]="false"
>
...
</ts-selection-list>
```

## Events

| Event | Description | Payload |
Expand Down
25 changes: 19 additions & 6 deletions terminus-ui/selection-list/src/selection-list.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
@import './../../scss/helpers/typography';


$transition-duration: 200;

.ts-selection-list {
// This brings chips above the static trigger
--chip-zIndex: 2;
cursor: cursor(pointer);
display: block;

Expand All @@ -24,15 +24,28 @@ $transition-duration: 200;
cursor: cursor(not-allowed);
}
}

// Static trigger when user input is not allowed
.ts-selection-list__custom-trigger {
cursor: cursor(pointer);
// This magic number forces the div to fill the same vertical space the input would normally
min-height: 19px;
// Don't let it fully collapse when empty
min-width: 1px;
}

.ts-chip-collection-wrapper {
z-index: 1;
}

.ts-chip {
z-index: var(--chip-zIndex);
}
}

.ts-selection-list__input-wrap {
position: relative;

&--hidden {
@include visually-hidden;
}

> .ts-icon {
position: absolute;
right: 0;
Expand Down
Loading

0 comments on commit 2fd2c4b

Please sign in to comment.