From 058ffda5bf3fb0222e6c987b8f7ab69cc5cf5189 Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Mon, 27 Mar 2017 17:24:19 -0700 Subject: [PATCH 01/17] feat(chips): remove TdAutocomplete and use MdAutocomplete There is no need to create a wrapper since it just adds complexity --- .../autocomplete/autocomplete.component.html | 26 ----- .../autocomplete/autocomplete.component.scss | 3 - .../autocomplete/autocomplete.component.ts | 108 ------------------ src/platform/core/chips/chips.component.html | 25 ++-- src/platform/core/chips/chips.module.ts | 6 +- 5 files changed, 20 insertions(+), 148 deletions(-) delete mode 100644 src/platform/core/chips/autocomplete/autocomplete.component.html delete mode 100644 src/platform/core/chips/autocomplete/autocomplete.component.scss delete mode 100644 src/platform/core/chips/autocomplete/autocomplete.component.ts diff --git a/src/platform/core/chips/autocomplete/autocomplete.component.html b/src/platform/core/chips/autocomplete/autocomplete.component.html deleted file mode 100644 index ebfbbaabac..0000000000 --- a/src/platform/core/chips/autocomplete/autocomplete.component.html +++ /dev/null @@ -1,26 +0,0 @@ -
- - - - - - - - -
diff --git a/src/platform/core/chips/autocomplete/autocomplete.component.scss b/src/platform/core/chips/autocomplete/autocomplete.component.scss deleted file mode 100644 index 9ade72b011..0000000000 --- a/src/platform/core/chips/autocomplete/autocomplete.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -:host { - display: block; -} \ No newline at end of file diff --git a/src/platform/core/chips/autocomplete/autocomplete.component.ts b/src/platform/core/chips/autocomplete/autocomplete.component.ts deleted file mode 100644 index 383f575dcd..0000000000 --- a/src/platform/core/chips/autocomplete/autocomplete.component.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { Component, Input, Output, forwardRef } from '@angular/core'; -import { EventEmitter } from '@angular/core'; -import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'; - -const noop: () => void = () => { - // empty method -}; - -export const TD_AUTOCOMPLETE_CONTROL_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TdAutoCompleteComponent), - multi: true, -}; - -@Component({ - providers: [ TD_AUTOCOMPLETE_CONTROL_VALUE_ACCESSOR ], - selector: 'td-autocomplete', - styleUrls: ['./autocomplete.component.scss' ], - templateUrl: './autocomplete.component.html', -}) -export class TdAutoCompleteComponent implements ControlValueAccessor { - - private _value: any = ''; - /** Callback registered via registerOnTouched (ControlValueAccessor) */ - private _onTouchedCallback: () => void = noop; - /** Callback registered via registerOnChange (ControlValueAccessor) */ - private _onChangeCallback: (_: any) => void = noop; - - listName: string = this.randomName(); - - @Input('name') name: string; - @Input('dividerColor') dividerColor: 'primary' | 'accent' | 'warn' = 'primary'; - @Input('placeholder') placeholder: string; - @Input('searchItems') searchItems: string[] = []; - @Input('readOnly') readOnly: boolean = false; - @Input('required') required: boolean = false; - @Input('disabled') disabled: boolean = false; - @Input('autoFocus') autoFocus: boolean = false; - @Input('max') max: string | number; - @Input('maxLength') maxLength: number; - @Input('min') min: string | number; - @Input('minLength') minLength: number; - - get value(): any { return this._value; }; - @Input() set value(v: any) { - if (v !== this._value) { - this._value = v; - this._onChangeCallback(v); - } - } - - @Output('itemSelect') itemSelect: EventEmitter = new EventEmitter(); - @Output('focus') focus: EventEmitter = new EventEmitter(); - @Output('blur') blur: EventEmitter = new EventEmitter(); - - clear(): boolean { - this.writeValue(''); - return true; - } - - randomName(): string { - let text: string = ''; - let possible: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - - for (let i: number = 0; i < 7; i++ ) { - text += possible.charAt(Math.floor(Math.random() * possible.length)); - } - - return text; - } - - handleItemSelect(): void { - this.itemSelect.emit(this._value); - } - - handleFocus(): void { - this.focus.emit(true); - } - - handleBlur(): void { - this.blur.emit(false); - } - - /** - * Implemented as part of ControlValueAccessor. - * TODO: internal - */ - writeValue(value: any): void { - this._value = value; - } - - /** - * Implemented as part of ControlValueAccessor. - * TODO: internal - */ - registerOnChange(fn: any): void { - this._onChangeCallback = fn; - } - - /** - * Implemented as part of ControlValueAccessor. - * TODO: internal - */ - registerOnTouched(fn: any): void { - this._onTouchedCallback = fn; - } - -} diff --git a/src/platform/core/chips/chips.component.html b/src/platform/core/chips/chips.component.html index d865990a16..56f103293a 100644 --- a/src/platform/core/chips/chips.component.html +++ b/src/platform/core/chips/chips.component.html @@ -9,13 +9,24 @@ title="Delete">cancel - +
+ + + + + + {{item}} + + +
Date: Mon, 27 Mar 2017 17:41:00 -0700 Subject: [PATCH 02/17] feat(chips): remove TdChipComponent and leverage md-chip-list and md-basic-chip --- src/platform/core/chips/_chips-theme.scss | 2 +- src/platform/core/chips/chip.component.html | 3 --- src/platform/core/chips/chip.component.scss | 5 ---- src/platform/core/chips/chip.component.ts | 10 -------- src/platform/core/chips/chips.component.html | 24 ++++++++++---------- src/platform/core/chips/chips.component.scss | 2 +- src/platform/core/chips/chips.module.ts | 7 ++---- 7 files changed, 16 insertions(+), 37 deletions(-) delete mode 100644 src/platform/core/chips/chip.component.html delete mode 100644 src/platform/core/chips/chip.component.scss delete mode 100644 src/platform/core/chips/chip.component.ts diff --git a/src/platform/core/chips/_chips-theme.scss b/src/platform/core/chips/_chips-theme.scss index 011ddaee5e..23a210428b 100644 --- a/src/platform/core/chips/_chips-theme.scss +++ b/src/platform/core/chips/_chips-theme.scss @@ -13,7 +13,7 @@ rgba(0, 0, 0, 0.26) 0%, rgba(0, 0, 0, 0.26) 33%, transparent 0%); // chip - .td-chip { + .mat-basic-chip { background: md-color($background, status-bar); color: md-color($foreground, text); md-icon { diff --git a/src/platform/core/chips/chip.component.html b/src/platform/core/chips/chip.component.html deleted file mode 100644 index b11973a6bb..0000000000 --- a/src/platform/core/chips/chip.component.html +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/src/platform/core/chips/chip.component.scss b/src/platform/core/chips/chip.component.scss deleted file mode 100644 index 8bf421a18b..0000000000 --- a/src/platform/core/chips/chip.component.scss +++ /dev/null @@ -1,5 +0,0 @@ -@import '../common/styles/mixins'; -:host { - display: block; - @include rtl(float, left, right); -} diff --git a/src/platform/core/chips/chip.component.ts b/src/platform/core/chips/chip.component.ts deleted file mode 100644 index 91fb2b812a..0000000000 --- a/src/platform/core/chips/chip.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'td-chip', - styleUrls: ['./chip.component.scss' ], - templateUrl: './chip.component.html', -}) -export class TdChipComponent { - -} diff --git a/src/platform/core/chips/chips.component.html b/src/platform/core/chips/chips.component.html index 56f103293a..09e9c75a01 100644 --- a/src/platform/core/chips/chips.component.html +++ b/src/platform/core/chips/chips.component.html @@ -1,15 +1,15 @@
- - - {{chip}} - cancel - - -
+ + + + {{chip}} + cancel + + {{item}} -
+
Date: Tue, 28 Mar 2017 15:48:18 -0700 Subject: [PATCH 03/17] feat(chips): filter items depending on input value for autocomplete --- src/platform/core/chips/chips.component.html | 7 +-- src/platform/core/chips/chips.component.ts | 54 ++++++++++++++++---- src/platform/core/chips/chips.module.ts | 4 +- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/src/platform/core/chips/chips.component.html b/src/platform/core/chips/chips.component.html index 09e9c75a01..1d368bb468 100644 --- a/src/platform/core/chips/chips.component.html +++ b/src/platform/core/chips/chips.component.html @@ -15,14 +15,15 @@ flex="100" #input [mdAutocomplete]="autocomplete" + [formControl]="inputControl" [placeholder]="readOnly? '' : placeholder" [readonly]="readOnly" - (keyup.enter)="matches = addItem(input.value); input.value = ''; input.blur()" + (keyup.enter)="(matches = addItem(input.value)) && input.value = ''" (focus)="handleFocus()" - (blur)="handleBlur(); matches = true; input.value = '';"> + (blur)="handleBlur(); matches = true;"> - + {{item}} diff --git a/src/platform/core/chips/chips.component.ts b/src/platform/core/chips/chips.component.ts index b41d3f4385..f88478c6f8 100644 --- a/src/platform/core/chips/chips.component.ts +++ b/src/platform/core/chips/chips.component.ts @@ -1,6 +1,8 @@ -import { Component, Input, Output, forwardRef, DoCheck } from '@angular/core'; +import { Component, Input, Output, forwardRef, DoCheck, ViewChild, OnInit } from '@angular/core'; import { EventEmitter } from '@angular/core'; -import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'; +import { NG_VALUE_ACCESSOR, ControlValueAccessor, FormControl } from '@angular/forms'; +import { Observable } from 'rxjs/Observable'; +import { Subject } from 'rxjs/Subject'; const noop: any = () => { // empty method @@ -18,7 +20,7 @@ export const TD_CHIPS_CONTROL_VALUE_ACCESSOR: any = { styleUrls: ['./chips.component.scss' ], templateUrl: './chips.component.html', }) -export class TdChipsComponent implements ControlValueAccessor, DoCheck { +export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { /** * Implemented as part of ControlValueAccessor. @@ -37,6 +39,21 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck { */ focused: boolean = false; + /** + * FormControl for the mdInput element. + */ + inputControl: FormControl = new FormControl(); + + /** + * Subject to control what items to render in the autocomplete + */ + subject: Subject = new Subject(); + + /** + * Observable of items to render in the autocomplete + */ + filteredItems: Observable = this.subject.asObservable(); + /** * items?: string[] * Enables Autocompletion with the provided list of strings. @@ -89,28 +106,35 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck { if (v !== this._value) { this._value = v; this._length = this._value ? this._value.length : 0; + if (this._value) { + this._filter(''); + } } } get value(): any { return this._value; }; + ngOnInit(): void { + this.inputControl.valueChanges + .subscribe((value: string) => { + this._filter(value); + }); + } + ngDoCheck(): void { // Throw onChange event only if array changes size. if (this._value && this._value.length !== this._length) { this._length = this._value.length; this.onChange(this._value); + this._filter(''); } } /** * Returns a list of filtered items. - * Removes the ones that have been added as value. */ - get filteredItems(): string[] { - if (!this._value) { - return []; - } + filter(val: string): string[] { return this.items.filter((item: string) => { - return this._value.indexOf(item) < 0; + return item.indexOf(val) > -1; }); } @@ -177,4 +201,16 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck { onChange = (_: any) => noop; onTouched = () => noop; + /** + * + * Method to filter the options for the autocomplete + */ + private _filter(value: string): void { + let items: string[] = this.filter(value); + items = items.filter((filteredItem: string) => { + return this._value ? this._value.indexOf(filteredItem) < 0 : true; + }); + this.subject.next(items); + } + } diff --git a/src/platform/core/chips/chips.module.ts b/src/platform/core/chips/chips.module.ts index 080b6ada69..f9818e5e1c 100644 --- a/src/platform/core/chips/chips.module.ts +++ b/src/platform/core/chips/chips.module.ts @@ -1,6 +1,6 @@ import { NgModule, ModuleWithProviders } from '@angular/core'; -import { FormsModule } from '@angular/forms'; +import { ReactiveFormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; import { MdInputModule, MdIconModule, MdAutocompleteModule, MdChipsModule } from '@angular/material'; @@ -10,7 +10,7 @@ export { TdChipsComponent } from './chips.component'; @NgModule({ imports: [ - FormsModule, + ReactiveFormsModule, CommonModule, MdInputModule, MdIconModule, From 365785735bde807bf637477a44129799f86d4a72 Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Tue, 28 Mar 2017 16:34:12 -0700 Subject: [PATCH 04/17] fix(chips): add debounceTime and clean input on chips add/remove --- src/platform/core/chips/chips.component.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/platform/core/chips/chips.component.ts b/src/platform/core/chips/chips.component.ts index f88478c6f8..59b3785dfb 100644 --- a/src/platform/core/chips/chips.component.ts +++ b/src/platform/core/chips/chips.component.ts @@ -107,7 +107,7 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { this._value = v; this._length = this._value ? this._value.length : 0; if (this._value) { - this._filter(''); + this._filter(this.inputControl.value); } } } @@ -115,6 +115,7 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { ngOnInit(): void { this.inputControl.valueChanges + .debounceTime(100) .subscribe((value: string) => { this._filter(value); }); @@ -125,7 +126,6 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { if (this._value && this._value.length !== this._length) { this._length = this._value.length; this.onChange(this._value); - this._filter(''); } } @@ -134,7 +134,7 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { */ filter(val: string): string[] { return this.items.filter((item: string) => { - return item.indexOf(val) > -1; + return val ? item.indexOf(val) > -1 : true; }); } @@ -154,6 +154,7 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { this._value.push(value); this.add.emit(value); this.onChange(this._value); + this.inputControl.setValue(''); return true; } @@ -169,6 +170,7 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { this._value.splice(index, 1); this.remove.emit(value); this.onChange(this._value); + this.inputControl.setValue(''); return true; } @@ -208,7 +210,7 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { private _filter(value: string): void { let items: string[] = this.filter(value); items = items.filter((filteredItem: string) => { - return this._value ? this._value.indexOf(filteredItem) < 0 : true; + return this._value && filteredItem ? this._value.indexOf(filteredItem) < 0 : true; }); this.subject.next(items); } From df79deae4a4177b3330bd720a54baea1d57f6545 Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Tue, 28 Mar 2017 16:43:07 -0700 Subject: [PATCH 05/17] fix(chips): change input label when incorrect + remove warn when value changes --- src/platform/core/chips/chips.component.html | 9 +++++---- src/platform/core/chips/chips.component.ts | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/platform/core/chips/chips.component.html b/src/platform/core/chips/chips.component.html index 1d368bb468..e13e2f8507 100644 --- a/src/platform/core/chips/chips.component.html +++ b/src/platform/core/chips/chips.component.html @@ -6,11 +6,12 @@ cancel + (click)="removeItem(chip)"> + cancel + - + + (blur)="handleBlur()"> diff --git a/src/platform/core/chips/chips.component.ts b/src/platform/core/chips/chips.component.ts index 59b3785dfb..cd79a31c21 100644 --- a/src/platform/core/chips/chips.component.ts +++ b/src/platform/core/chips/chips.component.ts @@ -117,6 +117,7 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { this.inputControl.valueChanges .debounceTime(100) .subscribe((value: string) => { + this.matches = true; this._filter(value); }); } @@ -181,6 +182,7 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { handleBlur(): boolean { this.focused = false; + this.matches = true; this.onTouched(); return true; } From a5c9031e86c49c6dee77995f1872783b817f12a3 Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Tue, 28 Mar 2017 17:03:35 -0700 Subject: [PATCH 06/17] fix(chips): filter options even if there is no ngModel --- src/platform/core/chips/chips.component.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/platform/core/chips/chips.component.ts b/src/platform/core/chips/chips.component.ts index cd79a31c21..216cc34198 100644 --- a/src/platform/core/chips/chips.component.ts +++ b/src/platform/core/chips/chips.component.ts @@ -120,6 +120,10 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { this.matches = true; this._filter(value); }); + // filter the autocomplete options after everything is rendered + Observable.timer().subscribe(() => { + this._filter(this.inputControl.value); + }); } ngDoCheck(): void { From 188a24a94bc102b468fdc09d13ab96304de349d8 Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Fri, 31 Mar 2017 13:19:24 -0700 Subject: [PATCH 07/17] feat(chips): add better a11y to td-chips --- src/platform/core/chips/_chips-theme.scss | 28 +++-- src/platform/core/chips/chips.component.html | 14 +-- src/platform/core/chips/chips.component.ts | 126 ++++++++++++++++++- 3 files changed, 146 insertions(+), 22 deletions(-) diff --git a/src/platform/core/chips/_chips-theme.scss b/src/platform/core/chips/_chips-theme.scss index 23a210428b..d0c96caa26 100644 --- a/src/platform/core/chips/_chips-theme.scss +++ b/src/platform/core/chips/_chips-theme.scss @@ -12,19 +12,25 @@ $md-input-underline-disabled-background-image: linear-gradient(to right, rgba(0, 0, 0, 0.26) 0%, rgba(0, 0, 0, 0.26) 33%, transparent 0%); - // chip - .mat-basic-chip { - background: md-color($background, status-bar); - color: md-color($foreground, text); - md-icon { - color: md-color($foreground, hint-text); - &:hover { - color: md-color($foreground, icon); - } - } - } // chips td-chips { + // chip + .mat-basic-chip { + background: md-color($background, status-bar); + color: md-color($foreground, text); + &:focus:not(.td-chip-disabled) { + background: md-color($primary); + &, md-icon { + color: mat-color($primary, default-contrast) + } + } + md-icon { + color: md-color($foreground, hint-text); + &:hover { + color: md-color($foreground, icon); + } + } + } .mat-input-underline { border-top: 1px solid md-color($foreground, hint-text); &.mat-disabled { diff --git a/src/platform/core/chips/chips.component.html b/src/platform/core/chips/chips.component.html index e13e2f8507..f49d8518a6 100644 --- a/src/platform/core/chips/chips.component.html +++ b/src/platform/core/chips/chips.component.html @@ -1,12 +1,10 @@
- - - + + + {{chip}} - + cancel @@ -18,7 +16,7 @@ [mdAutocomplete]="autocomplete" [formControl]="inputControl" [placeholder]="readOnly? '' : placeholder" - [readonly]="readOnly" + (keydown)="_inputKeydown($event)" (keyup.enter)="(matches = addItem(input.value)) && input.value = ''" (focus)="handleFocus()" (blur)="handleBlur()"> diff --git a/src/platform/core/chips/chips.component.ts b/src/platform/core/chips/chips.component.ts index 216cc34198..3a179141e1 100644 --- a/src/platform/core/chips/chips.component.ts +++ b/src/platform/core/chips/chips.component.ts @@ -1,6 +1,7 @@ -import { Component, Input, Output, forwardRef, DoCheck, ViewChild, OnInit } from '@angular/core'; +import { Component, Input, Output, forwardRef, DoCheck, ViewChild, ViewChildren, QueryList, OnInit, HostListener } from '@angular/core'; import { EventEmitter } from '@angular/core'; import { NG_VALUE_ACCESSOR, ControlValueAccessor, FormControl } from '@angular/forms'; +import { MdChip, MdInputDirective, ESCAPE, LEFT_ARROW, RIGHT_ARROW, DELETE, BACKSPACE } from '@angular/material'; import { Observable } from 'rxjs/Observable'; import { Subject } from 'rxjs/Subject'; @@ -29,6 +30,10 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { private _length: number = 0; private _requireMatch: boolean = false; + private _readOnly: boolean = false; + + @ViewChild(MdInputDirective) _inputChild: MdInputDirective; + @ViewChildren(MdChip) _chipsChildren: QueryList; /** * Boolean value that specifies if the input is valid against the provieded list. @@ -75,9 +80,20 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { /** * readOnly?: boolean - * Disables the chip input and removal. + * Disables the chips input and chip removal icon. */ - @Input('readOnly') readOnly: boolean = false; + @Input('readOnly') + set readOnly(readOnly: boolean) { + this._readOnly = readOnly; + if (readOnly) { + this.inputControl.disable(); + } else { + this.inputControl.enable(); + } + } + get readOnly(): boolean { + return this._readOnly; + } /** * placeholder?: string @@ -191,6 +207,82 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { return true; } + /** + * Programmatically focus the input. Since its the component entry point + */ + focus(): void { + this._inputChild.focus(); + } + + /** + * Passes relevant input key presses. + */ + _inputKeydown(event: KeyboardEvent): void { + switch (event.keyCode) { + case LEFT_ARROW: + case DELETE: + case BACKSPACE: + /** Check to see if input is empty when pressing left arrow to move to the last chip */ + if (!this._inputChild.value) { + this._focusLastChip(); + event.preventDefault(); + } + break; + case RIGHT_ARROW: + /** Check to see if input is empty when pressing right arrow to move to the first chip */ + if (!this._inputChild.value) { + this._focusFirstChip(); + event.preventDefault(); + } + break; + default: + // default + } + } + + /** + * Passes relevant chip key presses. + */ + _chipKeydown(event: KeyboardEvent, index: number): void { + switch (event.keyCode) { + case DELETE: + case BACKSPACE: + /** Check to see if not in [readOnly] state to delete a chip */ + if (!this.readOnly) { + /** + * Checks if deleting last single chip, to focus input afterwards + * Else check if its not the last chip of the list to focus the next one. + */ + if (index === (this._totalChips - 1) && index === 0) { + this.focus(); + } else if (index < (this._totalChips - 1)) { + this._focusChip(index + 1); + } + this.removeItem(this.value[index]); + } + break; + case LEFT_ARROW: + /** Check to see if left arrow was pressed while focusing the first chip to focus input next */ + if (index === 0) { + this.focus(); + event.stopPropagation(); + } + break; + case RIGHT_ARROW: + /** Check to see if right arrow was pressed while focusing the last chip to focus input next */ + if (index === (this._totalChips - 1)) { + this.focus(); + event.stopPropagation(); + } + break; + case ESCAPE: + this.focus(); + break; + default: + // default + } + } + /** * Implemented as part of ControlValueAccessor. */ @@ -221,4 +313,32 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { this.subject.next(items); } + /** + * Get total of chips + */ + private get _totalChips(): number { + let chips: MdChip[] = this._chipsChildren.toArray(); + return chips.length; + } + + /** + * Method to focus a desired chip by index + */ + private _focusChip(index: number): void { + /** check to see if index exists in the array before focusing */ + if (index > -1 && this._totalChips > index) { + this._chipsChildren.toArray()[index].focus(); + } + } + + /** Method to focus first chip */ + private _focusFirstChip(): void { + this._focusChip(0); + } + + /** MEthod to focus last chip */ + private _focusLastChip(): void { + this._focusChip(this._totalChips - 1); + } + } From bc911f1cbebfdeb4cdececc2a5178fecb6bdc617 Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Fri, 31 Mar 2017 13:24:59 -0700 Subject: [PATCH 08/17] feat(chips): polish code to add chips internally --- src/platform/core/chips/chips.component.html | 4 ++-- src/platform/core/chips/chips.component.ts | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/platform/core/chips/chips.component.html b/src/platform/core/chips/chips.component.html index f49d8518a6..7845caac9d 100644 --- a/src/platform/core/chips/chips.component.html +++ b/src/platform/core/chips/chips.component.html @@ -17,13 +17,13 @@ [formControl]="inputControl" [placeholder]="readOnly? '' : placeholder" (keydown)="_inputKeydown($event)" - (keyup.enter)="(matches = addItem(input.value)) && input.value = ''" + (keyup.enter)="addChip(input.value)" (focus)="handleFocus()" (blur)="handleBlur()"> - {{item}} + {{item}} diff --git a/src/platform/core/chips/chips.component.ts b/src/platform/core/chips/chips.component.ts index 3a179141e1..7243379fbc 100644 --- a/src/platform/core/chips/chips.component.ts +++ b/src/platform/core/chips/chips.component.ts @@ -163,20 +163,22 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { * Method that is executed when trying to create a new chip from the autocomplete. * returns 'true' if successful, 'false' if it fails. */ - addItem(value: string): boolean { + addChip(value: string): void { if (value.trim() === '' || this._value.indexOf(value) > -1) { - return false; + this.matches = false; + return; } if (this.items && this.requireMatch) { if (this.items.indexOf(value) < 0) { - return false; + this.matches = false; + return; } } this._value.push(value); this.add.emit(value); this.onChange(this._value); this.inputControl.setValue(''); - return true; + this.matches = true; } /** From a48bc8180024bd6dfad6bdf03ed53e055100234f Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Fri, 31 Mar 2017 13:26:18 -0700 Subject: [PATCH 09/17] fix(chips): still return boolean to check if successful or not when adding a chip --- src/platform/core/chips/chips.component.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/platform/core/chips/chips.component.ts b/src/platform/core/chips/chips.component.ts index 7243379fbc..0fd90bd0cd 100644 --- a/src/platform/core/chips/chips.component.ts +++ b/src/platform/core/chips/chips.component.ts @@ -163,15 +163,15 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { * Method that is executed when trying to create a new chip from the autocomplete. * returns 'true' if successful, 'false' if it fails. */ - addChip(value: string): void { + addChip(value: string): boolean { if (value.trim() === '' || this._value.indexOf(value) > -1) { this.matches = false; - return; + return false; } if (this.items && this.requireMatch) { if (this.items.indexOf(value) < 0) { this.matches = false; - return; + return false; } } this._value.push(value); @@ -179,6 +179,7 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { this.onChange(this._value); this.inputControl.setValue(''); this.matches = true; + return true; } /** From a1a92b36099acc1614f5e0f201c8c7fbc59f462a Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Fri, 31 Mar 2017 13:46:28 -0700 Subject: [PATCH 10/17] fix(chips): rename removeItem to removeChip --- src/platform/core/chips/chips.component.html | 2 +- src/platform/core/chips/chips.component.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform/core/chips/chips.component.html b/src/platform/core/chips/chips.component.html index 7845caac9d..eb15404543 100644 --- a/src/platform/core/chips/chips.component.html +++ b/src/platform/core/chips/chips.component.html @@ -4,7 +4,7 @@ {{chip}} - + cancel diff --git a/src/platform/core/chips/chips.component.ts b/src/platform/core/chips/chips.component.ts index 0fd90bd0cd..3bb570f787 100644 --- a/src/platform/core/chips/chips.component.ts +++ b/src/platform/core/chips/chips.component.ts @@ -186,7 +186,7 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { * Method that is executed when trying to remove a chip. * returns 'true' if successful, 'false' if it fails. */ - removeItem(value: string): boolean { + removeChip(value: string): boolean { let index: number = this._value.indexOf(value); if (index < 0) { return false; @@ -261,7 +261,7 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { } else if (index < (this._totalChips - 1)) { this._focusChip(index + 1); } - this.removeItem(this.value[index]); + this.removeChip(this.value[index]); } break; case LEFT_ARROW: From 27031ae498233d125a07e76593602263817cccc5 Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Fri, 31 Mar 2017 14:47:22 -0700 Subject: [PATCH 11/17] feat(chips): add marging to td-chips in docsx --- src/app/components/components/chips/chips.component.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/components/components/chips/chips.component.html b/src/app/components/components/chips/chips.component.html index ac7431d26a..0f674a2d02 100644 --- a/src/app/components/components/chips/chips.component.html +++ b/src/app/components/components/chips/chips.component.html @@ -7,7 +7,7 @@

Basic Demo

Demo - + Code @@ -35,7 +35,7 @@

Autocomplete Demo

Demo - + Code @@ -77,7 +77,7 @@

Autocomplete and requireMatch Demo

Demo - + Code From d09062a93f232c1ce0d27d576c6103751cdf52ed Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Sun, 2 Apr 2017 16:04:00 -0700 Subject: [PATCH 12/17] feat(chips): make input 0 width when readOnly so chips fit better --- src/platform/core/chips/chips.component.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/platform/core/chips/chips.component.html b/src/platform/core/chips/chips.component.html index eb15404543..7207d9caa8 100644 --- a/src/platform/core/chips/chips.component.html +++ b/src/platform/core/chips/chips.component.html @@ -9,7 +9,9 @@
- + Date: Sun, 2 Apr 2017 16:04:54 -0700 Subject: [PATCH 13/17] fix(chips): removed unneeded styles and added hover color to icon when focused --- src/platform/core/chips/_chips-theme.scss | 27 ++++------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/src/platform/core/chips/_chips-theme.scss b/src/platform/core/chips/_chips-theme.scss index d0c96caa26..0b839a7557 100644 --- a/src/platform/core/chips/_chips-theme.scss +++ b/src/platform/core/chips/_chips-theme.scss @@ -1,5 +1,4 @@ @import '~@angular/material/core/theming/theming'; -@import '~@angular/material/core/style/variables'; @mixin td-chips-theme($theme) { $primary: map-get($theme, primary); @@ -8,10 +7,6 @@ $background: map-get($theme, background); $foreground: map-get($theme, foreground); - // Gradient for showing the dashed line when the input is disabled. - $md-input-underline-disabled-background-image: linear-gradient(to right, - rgba(0, 0, 0, 0.26) 0%, rgba(0, 0, 0, 0.26) 33%, transparent 0%); - // chips td-chips { // chip @@ -21,7 +16,10 @@ &:focus:not(.td-chip-disabled) { background: md-color($primary); &, md-icon { - color: mat-color($primary, default-contrast) + color: mat-color($primary, default-contrast); + md-icon:hover { + color: md-color($foreground, icon); + } } } md-icon { @@ -31,22 +29,5 @@ } } } - .mat-input-underline { - border-top: 1px solid md-color($foreground, hint-text); - &.mat-disabled { - background-image: $md-input-underline-disabled-background-image; - } - .mat-input-ripple { - background-color: md-color($primary); - transition: transform $swift-ease-out-duration $swift-ease-out-timing-function, - opacity $swift-ease-out-duration $swift-ease-out-timing-function; - &.mat-accent { - background-color: md-color($accent); - } - &.mat-warn { - background-color: md-color($warn); - } - } - } } } \ No newline at end of file From efdbdb76fd65e3760e6337c2c90fef45f06deee9 Mon Sep 17 00:00:00 2001 From: KL186023 Date: Sun, 2 Apr 2017 16:24:04 -0700 Subject: [PATCH 14/17] update(styles): proper warn ripple for mdInput --- src/platform/core/common/styles/_input.scss | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/platform/core/common/styles/_input.scss b/src/platform/core/common/styles/_input.scss index 04017e7dfe..39857b8267 100644 --- a/src/platform/core/common/styles/_input.scss +++ b/src/platform/core/common/styles/_input.scss @@ -13,6 +13,14 @@ md-input-container { } .mat-input-underline { border-top-color: md-color($warn); + .mat-input-ripple { + background-color: md-color($warn); + } } } +} + +// Proper placeholder font size +.mat-input-placeholder-wrapper { + font-size: 16px; } \ No newline at end of file From d00c96472e1984a24639dd472a113161aa7f5418 Mon Sep 17 00:00:00 2001 From: KL186023 Date: Sun, 2 Apr 2017 16:24:22 -0700 Subject: [PATCH 15/17] update(docs): margin around td-chips instead of on it --- .../components/components/chips/chips.component.html | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/app/components/components/chips/chips.component.html b/src/app/components/components/chips/chips.component.html index 0f674a2d02..0d33c828fd 100644 --- a/src/app/components/components/chips/chips.component.html +++ b/src/app/components/components/chips/chips.component.html @@ -7,7 +7,9 @@

Basic Demo

Demo - +
+ +
Code @@ -35,7 +37,9 @@

Autocomplete Demo

Demo - +
+ +
Code @@ -77,7 +81,9 @@

Autocomplete and requireMatch Demo

Demo - +
+ +
Code From 5c3e2ffb4422959b3cf6dd7943c3221850b1f4bb Mon Sep 17 00:00:00 2001 From: KL186023 Date: Sun, 2 Apr 2017 16:37:14 -0700 Subject: [PATCH 16/17] udpate(chips): better margins around chips & input --- src/platform/core/chips/chips.component.scss | 47 +++++++++++--------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/platform/core/chips/chips.component.scss b/src/platform/core/chips/chips.component.scss index c25bc69c9c..7e5ba99368 100644 --- a/src/platform/core/chips/chips.component.scss +++ b/src/platform/core/chips/chips.component.scss @@ -3,26 +3,34 @@ :host { display: block; padding: 0px 5px 0px 5px; - /deep/ .mat-basic-chip { - display: inline-block; - cursor: default; - border-radius: 16px; - line-height: 32px; - @include rtl(margin, 8px 8px 0 0, 8px 0 0 8px); - padding: 0 12px; - box-sizing: border-box; - max-width: 100%; - position: relative; - md-icon { + /deep/ { + .mat-input-wrapper { + margin-bottom: 2px; + } + .mat-input-container { + margin-top: 8px; + } + .mat-basic-chip { + display: inline-block; + cursor: default; + border-radius: 16px; + line-height: 32px; + @include rtl(margin, 8px 8px 0 0, 8px 0 0 8px); + padding: 0 12px; + box-sizing: border-box; + max-width: 100%; position: relative; - top: 5px; - @include rtl(left, 5px, auto); - @include rtl(right, auto, 5px); - height: 18px; - width: 18px; - font-size: 19px; - &:hover { - cursor: pointer; + md-icon { + position: relative; + top: 5px; + @include rtl(left, 5px, auto); + @include rtl(right, auto, 5px); + height: 18px; + width: 18px; + font-size: 19px; + &:hover { + cursor: pointer; + } } } } @@ -32,7 +40,6 @@ position: relative; height: 1px; width: 100%; - margin-top: 4px; &.mat-disabled { border-top: 0; From 9440ca9e67ff9c92fa70724c4fd2e13820824286 Mon Sep 17 00:00:00 2001 From: KL186023 Date: Sun, 2 Apr 2017 16:52:15 -0700 Subject: [PATCH 17/17] update(docs): better demo markup --- .../components/chips/chips.component.html | 146 +++++++++--------- 1 file changed, 76 insertions(+), 70 deletions(-) diff --git a/src/app/components/components/chips/chips.component.html b/src/app/components/components/chips/chips.component.html index 0d33c828fd..20fb514f53 100644 --- a/src/app/components/components/chips/chips.component.html +++ b/src/app/components/components/chips/chips.component.html @@ -1,58 +1,29 @@ Chips & Autocomplete - Small blocks for multiple items + Autocomplete with chips and no custom inputs - -

Basic Demo

- - - Demo -
- -
-
- - Code + + + Demo +
+
Type and select a preset option:
+ +
+
+ + Code +

HTML:

- ]]> - -

Typescript:

- - - -
-
-
-
- - -

Autocomplete Demo

- - - Demo -
- -
-
- - Code -

HTML:

- - + ]]>

Typescript:

Autocomplete Demo 'need more?', ]; + itemsRequireMatch: string[] = this.items.slice(0, 6); + + toggleReadOnly(): void { + this.readOnly = !this.readOnly; + } } ]]> -
-
-
+ +
+
+ + + + - -

Autocomplete and requireMatch Demo

- - - Demo -
- -
-
- - Code + Autocomplete with custom inputs + Autocomplete demo allowing custom inputs + + + + Demo +
+
Type and select option or enter custom text and press enter:
+ +
+
+ + Code +

HTML:

+ ]]>

Typescript:

Autocomplete and requireMatch Demo 'need more?', ]; - itemsRequireMatch: string[] = this.items.slice(0, 6); - - toggleReadOnly(): void { - this.readOnly = !this.readOnly; - } } ]]> -
-
-
+ +
+
+ + + Custom chips + Demo allowing custom inputs for tags - - - + + + Demo +
+
Type any test and press enter:
+ +
+
+ + Code + +

HTML:

+ + + ]]> + +

Typescript:

+ + + +
+
+
TdChipsComponent