Skip to content

Commit 234f0d2

Browse files
committed
feat(chip-list): Implement FormFieldControl
BREAKING CHANGES: - Deprecated: @output() select, and @output() deselect - Added @output() onSelectionChange = EventEmitter<MdChipSelectionChange>
1 parent 87318bc commit 234f0d2

File tree

12 files changed

+1261
-205
lines changed

12 files changed

+1261
-205
lines changed

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

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

48-
49-
<md-form-field>
50-
<md-chip-list mdPrefix #chipList1>
51-
<md-chip *ngFor="let person of people" [color]="color" [selectable]="selectable"
48+
<button md-button (click)="tabIndex = (tabIndex === 0 ? -1 : 0)">
49+
Set tabIndex to {{tabIndex === 0 ? -1 : 0}}
50+
</button>
51+
<md-form-field class="has-chip-list">
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>
5557
</md-chip>
58+
<input placeholder="New Contributor..."
59+
[mdChipInputFor]="chipList1"
60+
[mdChipInputSeparatorKeyCodes]="separatorKeysCodes"
61+
[mdChipInputAddOnBlur]="false"
62+
(mdChipInputTokenEnd)="add($event)" />
5663
</md-chip-list>
57-
<input mdInput placeholder="New Contributor..."
58-
[mdChipInputFor]="chipList1"
59-
[mdChipInputSeparatorKeyCodes]="separatorKeysCodes"
60-
[mdChipInputAddOnBlur]="addOnBlur"
61-
(mdChipInputTokenEnd)="add($event)" />
6264
</md-form-field>
6365

6466

@@ -68,21 +70,37 @@ <h4>Form Field</h4>
6870
With <code>mdChipInput</code> the input work with chip-list
6971
</p>
7072

71-
<md-chip-list #chipList2>
72-
<md-chip *ngFor="let person of people" [color]="color" [selectable]="selectable"
73-
[removable]="removable" (remove)="remove(person)">
74-
{{person.name}}
75-
<md-icon mdChipRemove *ngIf="removable">cancel</md-icon>
76-
</md-chip>
77-
</md-chip-list>
7873
<md-form-field>
79-
<input mdInput placeholder="New Contributor..."
74+
<md-chip-list [tabIndex]="tabIndex" #chipList2 [(ngModel)]="selectedPeople" required>
75+
<md-chip *ngFor="let person of people" [color]="color" [selectable]="selectable"
76+
[removable]="removable" (remove)="remove(person)">
77+
{{person.name}}
78+
<md-icon mdChipRemove *ngIf="removable">cancel</md-icon>
79+
</md-chip>
80+
</md-chip-list>
81+
<input placeholder="New Contributor..."
8082
[mdChipInputFor]="chipList2"
8183
[mdChipInputSeparatorKeyCodes]="separatorKeysCodes"
8284
[mdChipInputAddOnBlur]="addOnBlur"
8385
(mdChipInputTokenEnd)="add($event)" />
8486
</md-form-field>
8587

88+
<p>
89+
Chips list without input
90+
</p>
91+
92+
93+
<md-form-field class="has-chip-list">
94+
<md-chip-list #chipList3>
95+
<md-chip *ngFor="let person of people" [color]="color" [selectable]="selectable"
96+
[removable]="removable" (remove)="remove(person)">
97+
{{person.name}}
98+
<md-icon mdChipRemove *ngIf="removable">cancel</md-icon>
99+
</md-chip>
100+
</md-chip-list>
101+
</md-form-field>
102+
103+
86104
<p>
87105
The example above has overridden the <code>[separatorKeys]</code> input to allow for
88106
<code>ENTER</code>, <code>COMMA</code> and <code>SEMI COLON</code> keys.
@@ -108,6 +126,17 @@ <h4>Stacked Chips</h4>
108126
{{aColor.name}}
109127
</md-chip>
110128
</md-chip-list>
129+
130+
<h4>NgModel with chip list</h4>
131+
<md-chip-list [(ngModel)]="selectedColors">
132+
<md-chip *ngFor="let aColor of availableColors" color="{{aColor.color}}"
133+
[value]="aColor.name" (remove)="removeColor(aColor)">
134+
{{aColor.name}}
135+
<md-icon mdChipRemove>cancel</md-icon>
136+
</md-chip>
137+
</md-chip-list>
138+
139+
The selected colors are <span *ngFor="let color of selectedColors"> {{color}}</span>.
111140
</md-card-content>
112141
</md-card>
113142
</div>

src/demo-app/chips/chips-demo.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,7 @@
2525
width: 150px;
2626
}
2727
}
28+
29+
.has-chip-list {
30+
width: 100%;
31+
}

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

Lines changed: 18 additions & 0 deletions
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;
@@ -29,6 +30,8 @@ export class ChipsDemo {
2930
// Enter, comma, semi-colon
3031
separatorKeysCodes = [ENTER, COMMA, 186];
3132

33+
selectedPeople = null;
34+
3235
people: Person[] = [
3336
{ name: 'Kara' },
3437
{ name: 'Jeremy' },
@@ -72,7 +75,22 @@ export class ChipsDemo {
7275
}
7376
}
7477

78+
removeColor(color: DemoColor) {
79+
let index = this.availableColors.indexOf(color);
80+
81+
if (index >= 0) {
82+
this.availableColors.splice(index, 1);
83+
}
84+
85+
index = this.selectedColors.indexOf(color.name);
86+
87+
if (index >= 0) {
88+
this.selectedColors.splice(index, 1);
89+
}
90+
}
91+
7592
toggleVisible(): void {
7693
this.visible = false;
7794
}
95+
selectedColors: any[] = ['Primary', 'Warn'];
7896
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {async, TestBed, ComponentFixture} from '@angular/core/testing';
22
import {MdChipsModule} from './index';
33
import {Component, DebugElement} from '@angular/core';
4+
import {PlatformModule} from '../core/platform/index';
45
import {MdChipInput, MdChipInputEvent} from './chip-input';
56
import {By} from '@angular/platform-browser';
67
import {Directionality} from '../core';
@@ -21,7 +22,7 @@ describe('MdChipInput', () => {
2122

2223
beforeEach(async(() => {
2324
TestBed.configureTestingModule({
24-
imports: [MdChipsModule],
25+
imports: [MdChipsModule, PlatformModule],
2526
declarations: [TestChipInput],
2627
providers: [{
2728
provide: Directionality, useFactory: () => {

src/lib/chips/chip-input.ts

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,47 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {Directive, Output, EventEmitter, ElementRef, Input} from '@angular/core';
9+
import {
10+
Directive,
11+
ElementRef,
12+
Output,
13+
EventEmitter,
14+
Inject,
15+
Input,
16+
Optional,
17+
Renderer2,
18+
Self,
19+
} from '@angular/core';
20+
import {FormGroupDirective, NgControl, NgForm} from '@angular/forms';
21+
import {Platform} from '@angular/cdk/platform';
1022
import {coerceBooleanProperty} from '@angular/cdk/coercion';
1123
import {ENTER} from '../core/keyboard/keycodes';
1224
import {MdChipList} from './chip-list';
25+
import {MdInput} from '../input/input';
26+
import {
27+
ErrorOptions,
28+
MD_ERROR_GLOBAL_OPTIONS
29+
} from '../core/error/error-options';
1330

1431
export interface MdChipInputEvent {
1532
input: HTMLInputElement;
1633
value: string;
1734
}
1835

36+
/**
37+
* Directive that adds chip-specific behaviors to an input element inside <md-form-field>.
38+
* May be placed inside or outside of an <md-chip-list>.
39+
*/
1940
@Directive({
2041
selector: 'input[mdChipInputFor], input[matChipInputFor]',
2142
host: {
22-
'class': 'mat-chip-input',
43+
'class': 'mat-chip-input mat-input-element',
2344
'(keydown)': '_keydown($event)',
24-
'(blur)': '_blur()'
45+
'(blur)': '_blur()',
46+
'(focus)': '_focus()',
2547
}
2648
})
27-
export class MdChipInput {
49+
export class MdChipInput extends MdInput {
2850

2951
_chipList: MdChipList;
3052

@@ -33,7 +55,7 @@ export class MdChipInput {
3355
set chipList(value: MdChipList) {
3456
if (value) {
3557
this._chipList = value;
36-
this._chipList.registerInput(this._inputElement);
58+
this._chipList.registerInput(this);
3759
}
3860
}
3961

@@ -71,7 +93,15 @@ export class MdChipInput {
7193
/** The native input element to which this directive is attached. */
7294
protected _inputElement: HTMLInputElement;
7395

74-
constructor(protected _elementRef: ElementRef) {
96+
constructor(protected _elementRef: ElementRef,
97+
protected _renderer: Renderer2,
98+
protected _platform: Platform,
99+
@Optional() @Self() public ngControl: NgControl,
100+
@Optional() protected _parentForm: NgForm,
101+
@Optional() protected _parentFormGroup: FormGroupDirective,
102+
@Optional() @Inject(MD_ERROR_GLOBAL_OPTIONS) errorOptions: ErrorOptions) {
103+
super(_elementRef, _renderer, _platform, ngControl, _parentForm,
104+
_parentFormGroup, errorOptions);
75105
this._inputElement = this._elementRef.nativeElement as HTMLInputElement;
76106
}
77107

@@ -85,6 +115,17 @@ export class MdChipInput {
85115
if (this.addOnBlur) {
86116
this._emitChipEnd();
87117
}
118+
super._focusChanged(false);
119+
// Blur the chip list if it is not focused
120+
if (!this._chipList.focused) {
121+
this._chipList._blur();
122+
}
123+
this._chipList.stateChanges.next();
124+
}
125+
126+
_focus() {
127+
super._focusChanged(true);
128+
this._chipList.stateChanges.next();
88129
}
89130

90131
/** Checks to see if the (chipEnd) event needs to be emitted. */

0 commit comments

Comments
 (0)