Skip to content

Commit c19c278

Browse files
committed
Address comments
1 parent 1e6c897 commit c19c278

File tree

6 files changed

+103
-89
lines changed

6 files changed

+103
-89
lines changed

src/demo-app/chips/chips-demo.html

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,12 @@ <h4>Form Field</h4>
4545
<code>&lt;md-form-field&gt;</code>.
4646
</p>
4747

48-
48+
<button md-button (click)="tabIndex = (tabIndex === 0 ? -1 : 0)">
49+
Set tabIndex to {{tabIndex === 0 ? -1 : 0}}
50+
</button>
4951
<md-form-field class="has-chip-list">
50-
<md-chip-list #chipList1 [(ngModel)]="selectedPeople" required>
51-
<md-chip *ngFor="let person of people" [color]="color" [selectable]="selectable"
52+
<md-chip-list [tabIndex]="tabIndex" #chipList1 [(ngModel)]="selectedPeople" required>
53+
<md-chip *ngFor="let person of people" [color]="color" [selectable]="selectable"
5254
[removable]="removable" (remove)="remove(person)">
5355
{{person.name}}
5456
<md-icon mdChipRemove *ngIf="removable">cancel</md-icon>
@@ -69,7 +71,7 @@ <h4>Form Field</h4>
6971
</p>
7072

7173
<md-form-field>
72-
<md-chip-list #chipList2>
74+
<md-chip-list [tabIndex]="tabIndex" #chipList2 [(ngModel)]="selectedPeople" required>
7375
<md-chip *ngFor="let person of people" [color]="color" [selectable]="selectable"
7476
[removable]="removable" (remove)="remove(person)">
7577
{{person.name}}

src/demo-app/chips/chips-demo.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export interface DemoColor {
1919
styleUrls: ['chips-demo.css']
2020
})
2121
export class ChipsDemo {
22+
tabIndex: number = 0;
2223
visible: boolean = true;
2324
color: string = '';
2425
selectable: boolean = true;
@@ -91,5 +92,5 @@ export class ChipsDemo {
9192
toggleVisible(): void {
9293
this.visible = false;
9394
}
94-
selectedColors: any[] = ["Primary", "Warn"];
95+
selectedColors: any[] = ['Primary', 'Warn'];
9596
}

src/lib/chips/chip-input.ts

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,14 @@ import {
1717
Renderer2,
1818
Self,
1919
} from '@angular/core';
20-
import {FormControl, FormGroupDirective, NgControl, NgForm} from '@angular/forms';
21-
import {Platform, getSupportedInputTypes} from '@angular/cdk/platform';
20+
import {FormGroupDirective, NgControl, NgForm} from '@angular/forms';
21+
import {Platform} from '@angular/cdk/platform';
2222
import {coerceBooleanProperty} from '@angular/cdk/coercion';
2323
import {ENTER} from '../core/keyboard/keycodes';
2424
import {MdChipList} from './chip-list';
2525
import {MdInput} from '../input/input';
2626
import {
27-
defaultErrorStateMatcher,
2827
ErrorOptions,
29-
ErrorStateMatcher,
3028
MD_ERROR_GLOBAL_OPTIONS
3129
} from '../core/error/error-options';
3230

@@ -35,6 +33,27 @@ export interface MdChipInputEvent {
3533
value: string;
3634
}
3735

36+
/**
37+
* A material design chips input component working with chip list component.
38+
* To be placed inside md-form-field. Can be placed inside <md-chip-list> or outside <md-chip-list>.
39+
*
40+
* Example:
41+
* <md-form-field>
42+
* <md-chip-list #chipList>
43+
* <md-chip>Chip 1<md-chip>
44+
* <md-chip>Chip 2<md-chip>
45+
* </md-chip-list>
46+
* <input mdChipInputFor="chipList">
47+
* </md-form-field>
48+
*
49+
* <md-form-field>
50+
* <md-chip-list #chipList>
51+
* <md-chip>Chip 1<md-chip>
52+
* <md-chip>Chip 2<md-chip>
53+
* <input mdChipInputFor="chipList">
54+
* </md-chip-list>
55+
* </md-form-field>
56+
*/
3857
@Directive({
3958
selector: 'input[mdChipInputFor], input[matChipInputFor]',
4059
host: {
@@ -98,7 +117,8 @@ export class MdChipInput extends MdInput {
98117
@Optional() protected _parentForm: NgForm,
99118
@Optional() protected _parentFormGroup: FormGroupDirective,
100119
@Optional() @Inject(MD_ERROR_GLOBAL_OPTIONS) errorOptions: ErrorOptions) {
101-
super(_elementRef, _renderer, _platform, ngControl, _parentForm, _parentFormGroup, errorOptions);
120+
super(_elementRef, _renderer, _platform, ngControl, _parentForm,
121+
_parentFormGroup, errorOptions);
102122
this._inputElement = this._elementRef.nativeElement as HTMLInputElement;
103123
}
104124

@@ -113,6 +133,10 @@ export class MdChipInput extends MdInput {
113133
this._emitChipEnd();
114134
}
115135
super._focusChanged(false);
136+
// Blur the chip list if it is not focused
137+
if (!this._chipList.focused) {
138+
this._chipList._blur();
139+
}
116140
this._chipList.stateChanges.next();
117141
}
118142

src/lib/chips/chip-list.spec.ts

Lines changed: 35 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,26 @@
11
import {async, ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing';
22
import {
3-
ChangeDetectionStrategy,
43
Component,
54
DebugElement,
6-
OnInit,
75
QueryList,
86
ViewChild,
97
ViewChildren,
108
} from '@angular/core';
119
import {
12-
ControlValueAccessor,
1310
FormControl,
14-
FormGroup,
15-
FormGroupDirective,
1611
FormsModule,
17-
NG_VALUE_ACCESSOR,
1812
ReactiveFormsModule,
19-
Validators,
2013
} from '@angular/forms';
2114
import {By} from '@angular/platform-browser';
2215
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
2316
import {MdChipList, MdChipsModule} from './index';
2417
import {FocusKeyManager} from '@angular/cdk/a11y';
25-
import {createKeyboardEvent, dispatchFakeEvent, dispatchKeyboardEvent, wrappedErrorMessage} from '@angular/cdk/testing';
18+
import {createKeyboardEvent, dispatchFakeEvent, dispatchKeyboardEvent} from '@angular/cdk/testing';
2619

2720
import {MdInputModule} from '../input/index';
28-
import {LEFT_ARROW, RIGHT_ARROW, BACKSPACE, DELETE, SPACE, TAB, ENTER} from '../core/keyboard/keycodes';
21+
import {LEFT_ARROW, RIGHT_ARROW, BACKSPACE, DELETE, SPACE, TAB, ENTER}
22+
from '../core/keyboard/keycodes';
2923
import {Directionality} from '../core';
30-
import {extendObject} from '../core/util/object-extend';
3124
import {MdFormFieldModule} from '../form-field/index';
3225
import {MdChip} from './chip';
3326
import {MdChipInputEvent} from './chip-input';
@@ -336,7 +329,6 @@ describe('MdChipList', () => {
336329
});
337330

338331
describe('selection logic', () => {
339-
let fixture: ComponentFixture<BasicChipList>;
340332
let formField: HTMLElement;
341333
let nativeChips: HTMLElement[];
342334

@@ -398,23 +390,21 @@ describe('MdChipList', () => {
398390
});
399391

400392
it('should not select disabled chips', () => {
401-
const chips = fixture.componentInstance.chips.toArray();
402-
393+
const array = chips.toArray();
403394
const disabledChip = nativeChips[2];
404395
dispatchKeyboardEvent(disabledChip, 'keydown', SPACE);
405396
fixture.detectChanges();
406397

407398
expect(fixture.componentInstance.chipList.value)
408399
.toBeUndefined('Expect value to be undefined');
409-
expect(chips[2].selected).toBeFalsy('Expect disabled chip not selected');
400+
expect(array[2].selected).toBeFalsy('Expect disabled chip not selected');
410401
expect(fixture.componentInstance.chipList.selected.length)
411402
.toBe(0, 'Expect no selected chips');
412403
});
413404

414405
});
415406

416407
describe('forms integration', () => {
417-
let fixture: ComponentFixture<BasicChipList>;
418408
let formField: HTMLElement;
419409
let nativeChips: HTMLElement[];
420410

@@ -425,33 +415,33 @@ describe('MdChipList', () => {
425415
formField = fixture.debugElement.query(By.css('.mat-form-field')).nativeElement;
426416
nativeChips = fixture.debugElement.queryAll(By.css('md-chip'))
427417
.map((chip) => chip.nativeElement);
418+
chips = fixture.componentInstance.chips;
428419
});
429420

430421
it('should take an initial view value with reactive forms', () => {
431422
fixture.componentInstance.control = new FormControl(['pizza-1']);
432423
fixture.detectChanges();
433424

434-
const chipList = fixture.componentInstance.chipList;
435-
const chips = fixture.componentInstance.chips.toArray();
425+
const array = chips.toArray();
436426

437-
expect(chips[1].selected).toBeTruthy('Expect pizza-1 chip to be selected');
427+
expect(array[1].selected).toBeTruthy('Expect pizza-1 chip to be selected');
438428

439429
dispatchKeyboardEvent(nativeChips[1], 'keydown', SPACE);
440430
fixture.detectChanges();
441431

442-
expect(chips[1].selected).toBeFalsy('Expect chip to be not selected after toggle selected');
432+
expect(array[1].selected).toBeFalsy('Expect chip to be not selected after toggle selected');
443433
});
444434

445435
it('should set the view value from the form', () => {
446436
const chipList = fixture.componentInstance.chipList;
447-
const chips = fixture.componentInstance.chips.toArray();
437+
const array = chips.toArray();
448438

449439
expect(chipList.value).toBeFalsy('Expect chip list to have no initial value');
450440

451441
fixture.componentInstance.control.setValue(['pizza-1']);
452442
fixture.detectChanges();
453443

454-
expect(chips[1].selected).toBeTruthy('Expect chip to be selected');
444+
expect(array[1].selected).toBeTruthy('Expect chip to be selected');
455445
});
456446

457447
it('should update the form value when the view changes', () => {
@@ -467,42 +457,37 @@ describe('MdChipList', () => {
467457
});
468458

469459
it('should clear the selection when a nonexistent option value is selected', () => {
470-
const chipList = fixture.componentInstance.chipList;
471-
const chips = fixture.componentInstance.chips.toArray();
460+
const array = chips.toArray();
472461

473462
fixture.componentInstance.control.setValue(['pizza-1']);
474463
fixture.detectChanges();
475464

476-
expect(chips[1].selected)
465+
expect(array[1].selected)
477466
.toBeTruthy(`Expected chip with the value to be selected.`);
478467

479468
fixture.componentInstance.control.setValue(['gibberish']);
480469

481470
fixture.detectChanges();
482471

483-
expect(chips[1].selected)
472+
expect(array[1].selected)
484473
.toBeFalsy(`Expected chip with the old value not to be selected.`);
485474
});
486475

487476

488477
it('should clear the selection when the control is reset', () => {
489-
const chipList = fixture.componentInstance.chipList;
490-
const chips = fixture.componentInstance.chips.toArray();
478+
const array = chips.toArray();
491479

492480
fixture.componentInstance.control.setValue(['pizza-1']);
493481
fixture.detectChanges();
494482

495483
fixture.componentInstance.control.reset();
496484
fixture.detectChanges();
497485

498-
expect(chips[1].selected)
486+
expect(array[1].selected)
499487
.toBeFalsy(`Expected chip with the old value not to be selected.`);
500488
});
501489

502490
it('should set the control to touched when the chip list is touched', () => {
503-
const chipList = fixture.componentInstance.chipList;
504-
const chips = fixture.componentInstance.chips.toArray();
505-
506491
expect(fixture.componentInstance.control.touched)
507492
.toBe(false, 'Expected the control to start off as untouched.');
508493

@@ -514,9 +499,6 @@ describe('MdChipList', () => {
514499
});
515500

516501
it('should not set touched when a disabled chip list is touched', () => {
517-
const chipList = fixture.componentInstance.chipList;
518-
const chips = fixture.componentInstance.chips.toArray();
519-
520502
expect(fixture.componentInstance.control.touched)
521503
.toBe(false, 'Expected the control to start off as untouched.');
522504

@@ -579,7 +561,6 @@ describe('MdChipList', () => {
579561
});
580562

581563
describe('chip list with chip input', () => {
582-
let fixture: ComponentFixture<InputChipList>;
583564
let formField: HTMLElement;
584565
let nativeChips: HTMLElement[];
585566

@@ -596,27 +577,25 @@ describe('MdChipList', () => {
596577
fixture.componentInstance.control = new FormControl(['pizza-1']);
597578
fixture.detectChanges();
598579

599-
const chipList = fixture.componentInstance.chipList;
600-
const chips = fixture.componentInstance.chips.toArray();
580+
const array = fixture.componentInstance.chips.toArray();
601581

602-
expect(chips[1].selected).toBeTruthy('Expect pizza-1 chip to be selected');
582+
expect(array[1].selected).toBeTruthy('Expect pizza-1 chip to be selected');
603583

604584
dispatchKeyboardEvent(nativeChips[1], 'keydown', SPACE);
605585
fixture.detectChanges();
606586

607-
expect(chips[1].selected).toBeFalsy('Expect chip to be not selected after toggle selected');
587+
expect(array[1].selected).toBeFalsy('Expect chip to be not selected after toggle selected');
608588
});
609589

610590
it('should set the view value from the form', () => {
611-
const chipList = fixture.componentInstance.chipList;
612-
const chips = fixture.componentInstance.chips.toArray();
591+
const array = fixture.componentInstance.chips.toArray();
613592

614-
expect(chips[1].selected).toBeFalsy('Expect chip to not be selected');
593+
expect(array[1].selected).toBeFalsy('Expect chip to not be selected');
615594

616595
fixture.componentInstance.control.setValue(['pizza-1']);
617596
fixture.detectChanges();
618597

619-
expect(chips[1].selected).toBeTruthy('Expect chip to be selected');
598+
expect(array[1].selected).toBeTruthy('Expect chip to be selected');
620599
});
621600

622601
it('should update the form value when the view changes', () => {
@@ -632,56 +611,52 @@ describe('MdChipList', () => {
632611
});
633612

634613
it('should clear the selection when a nonexistent option value is selected', () => {
635-
const chipList = fixture.componentInstance.chipList;
636-
const chips = fixture.componentInstance.chips.toArray();
614+
const array = fixture.componentInstance.chips.toArray();
637615

638616
fixture.componentInstance.control.setValue(['pizza-1']);
639617
fixture.detectChanges();
640618

641-
expect(chips[1].selected)
619+
expect(array[1].selected)
642620
.toBeTruthy(`Expected chip with the value to be selected.`);
643621

644622
fixture.componentInstance.control.setValue(['gibberish']);
645623

646624
fixture.detectChanges();
647625

648-
expect(chips[1].selected)
626+
expect(array[1].selected)
649627
.toBeFalsy(`Expected chip with the old value not to be selected.`);
650628
});
651629

652630

653631
it('should clear the selection when the control is reset', () => {
654-
const chipList = fixture.componentInstance.chipList;
655-
const chips = fixture.componentInstance.chips.toArray();
632+
const array = fixture.componentInstance.chips.toArray();
656633

657634
fixture.componentInstance.control.setValue(['pizza-1']);
658635
fixture.detectChanges();
659636

660637
fixture.componentInstance.control.reset();
661638
fixture.detectChanges();
662639

663-
expect(chips[1].selected)
640+
expect(array[1].selected)
664641
.toBeFalsy(`Expected chip with the old value not to be selected.`);
665642
});
666643

667-
it('should set the control to touched when the chip list is touched', () => {
668-
const chipList = fixture.componentInstance.chipList;
669-
const chips = fixture.componentInstance.chips.toArray();
670-
644+
it('should set the control to touched when the chip list is touched', async(() => {
671645
expect(fixture.componentInstance.control.touched)
672646
.toBe(false, 'Expected the control to start off as untouched.');
673647

674648
const nativeChipList = fixture.debugElement.query(By.css('.mat-chip-list')).nativeElement;
649+
const nativeInput = fixture.debugElement.query(By.css('.mat-chip-input')).nativeElement;
650+
675651
dispatchFakeEvent(nativeChipList, 'blur');
676652

677-
expect(fixture.componentInstance.control.touched)
678-
.toBe(true, 'Expected the control to be touched.');
679-
});
653+
fixture.whenStable().then(() => {
654+
expect(fixture.componentInstance.control.touched)
655+
.toBe(true, 'Expected the control to be touched.');
656+
});
657+
}));
680658

681659
it('should not set touched when a disabled chip list is touched', () => {
682-
const chipList = fixture.componentInstance.chipList;
683-
const chips = fixture.componentInstance.chips.toArray();
684-
685660
expect(fixture.componentInstance.control.touched)
686661
.toBe(false, 'Expected the control to start off as untouched.');
687662

0 commit comments

Comments
 (0)