Skip to content

Commit

Permalink
Add chip list container
Browse files Browse the repository at this point in the history
  • Loading branch information
tinayuangao committed Jun 1, 2017
1 parent 03d293e commit afe6a4f
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 85 deletions.
7 changes: 1 addition & 6 deletions src/demo-app/chips/chips-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,24 +44,19 @@ <h4>Input Container</h4>
<code>&lt;md-input-container&gt;</code>.
</p>

<md-input-container>
<md-input-container mdChipListContainer>
<md-chip-list mdPrefix #chipList>
<md-chip *ngFor="let person of people" [color]="color" [selectable]="selectable"
[removable]="removable" (remove)="remove(person)">
{{person.name}}
<md-icon mdChipRemove>cancel</md-icon>
</md-chip>

</md-chip-list>
<input mdInput placeholder="New Contributor..."
[mdChipList] ="chipList" (chipAdded)="add($event)"
[separatorKeys]="separatorKeys" [addOnBlur]="addOnBlur" />
</md-input-container>

<md-input-container>
<input mdInput placeholder="New Contributor..."/>
</md-input-container>

<p>
The example above has overridden the <code>[separatorKeys]</code> input to allow for
<code>ENTER</code>, <code>COMMA</code> and <code>SEMI COLON</code> keys.
Expand Down
4 changes: 2 additions & 2 deletions src/lib/chips/chip-input.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ describe('MdChipInput', () => {
@Component({
template: `
<md-chip-list>
<input mdChipInput [addOnBlur]="addOnBlur" [separatorKeys]="separatorKeys"
(chipAdded)="add($event)" />
</md-chip-list>
<input mdInput mdChipList [addOnBlur]="addOnBlur" [separatorKeys]="separatorKeys"
(chipAdded)="add($event)" />
`
})
class TestChipInput {
Expand Down
37 changes: 16 additions & 21 deletions src/lib/chips/chip-list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('MdChipList', () => {
setupStandardList();
}));

it('adds the `mat-chip-list` class', () => {
it('should add the `mat-chip-list` class', () => {
expect(chipListNativeElement.classList).toContain('mat-chip-list');
});
});
Expand All @@ -58,7 +58,7 @@ describe('MdChipList', () => {
manager = chipListInstance._keyManager;
});

it('focuses the first chip on focus', () => {
it('should focus the first chip on focus', () => {
let FOCUS_EVENT = {} as Event;

chipListInstance.focus(FOCUS_EVENT);
Expand All @@ -67,7 +67,7 @@ describe('MdChipList', () => {
expect(manager.activeItemIndex).toBe(0);
});

it('watches for chip focus', () => {
it('should watch for chip focus', () => {
let array = chips.toArray();
let lastIndex = array.length - 1;
let lastItem = array[lastIndex];
Expand All @@ -79,7 +79,7 @@ describe('MdChipList', () => {
});

describe('on chip destroy', () => {
it('focuses the next item', () => {
it('should focus the next item', () => {
let array = chips.toArray();
let midItem = array[2];

Expand All @@ -95,7 +95,7 @@ describe('MdChipList', () => {
});


it('focuses the previous item', () => {
it('should focus the previous item', () => {
let array = chips.toArray();
let lastIndex = array.length - 1;
let lastItem = array[lastIndex];
Expand All @@ -121,7 +121,7 @@ describe('MdChipList', () => {
manager = chipListInstance._keyManager;
}));

it('LEFT ARROW focuses previous item', () => {
it('should focus previous item when press LEFT ARROW', () => {
let nativeChips = chipListNativeElement.querySelectorAll('md-chip');
let lastNativeChip = nativeChips[nativeChips.length - 1] as HTMLElement;

Expand All @@ -142,7 +142,7 @@ describe('MdChipList', () => {
expect(manager.activeItemIndex).toEqual(lastIndex - 1);
});

it('RIGHT ARROW focuses next item', () => {
it('should focus next item when press RIGHT ARROW', () => {
let nativeChips = chipListNativeElement.querySelectorAll('md-chip');
let firstNativeChip = nativeChips[0] as HTMLElement;

Expand Down Expand Up @@ -172,7 +172,7 @@ describe('MdChipList', () => {
manager = chipListInstance._keyManager;
}));

it('RIGHT ARROW focuses previous item', () => {
it('should focus previous item when press RIGHT ARROW', () => {
let nativeChips = chipListNativeElement.querySelectorAll('md-chip');
let lastNativeChip = nativeChips[nativeChips.length - 1] as HTMLElement;

Expand All @@ -194,7 +194,7 @@ describe('MdChipList', () => {
expect(manager.activeItemIndex).toEqual(lastIndex - 1);
});

it('LEFT ARROW focuses next item', () => {
it('should focus next item when press LEFT ARROW', () => {
let nativeChips = chipListNativeElement.querySelectorAll('md-chip');
let firstNativeChip = nativeChips[0] as HTMLElement;

Expand All @@ -215,7 +215,7 @@ describe('MdChipList', () => {
expect(manager.activeItemIndex).toEqual(1);
});

it('allow focus to escape when tabbing away', fakeAsync(() => {
it('should allow focus to escape when tabbing away', fakeAsync(() => {
chipListInstance._keyManager.onKeydown(createKeyboardEvent('keydown', TAB));

expect(chipListInstance._tabIndex)
Expand All @@ -240,15 +240,10 @@ describe('MdChipList', () => {
manager = chipListInstance._keyManager;
});

it('SPACE ignores selection', () => {
let SPACE_EVENT = createKeyboardEvent('keydown', SPACE);
let firstChip: MdChip = chips.toArray()[0];
});

describe('when the input has focus', () => {

it('DELETE focuses the last chip', () => {
let nativeInput = chipListNativeElement.querySelector('input');
it('should focus the last chip when press DELETE', () => {
let nativeInput = fixture.nativeElement.querySelector('input');
let DELETE_EVENT: KeyboardEvent =
createKeyboardEvent('keydown', DELETE, nativeInput);

Expand All @@ -264,8 +259,8 @@ describe('MdChipList', () => {
expect(manager.activeItemIndex).toEqual(chips.length - 1);
});

it('BACKSPACE focuses the last chip', () => {
let nativeInput = chipListNativeElement.querySelector('input');
it('should focus the last chip when press BACKSPACE', () => {
let nativeInput = fixture.nativeElement.querySelector('input');
let BACKSPACE_EVENT: KeyboardEvent =
createKeyboardEvent('keydown', BACKSPACE, nativeInput);

Expand Down Expand Up @@ -336,12 +331,12 @@ class StandardChipList {
@Component({
template: `
<md-input-container>
<md-chip-list>
<md-chip-list mdPrefix #chipList>
<md-chip>Chip 1</md-chip>
<md-chip>Chip 1</md-chip>
<md-chip>Chip 1</md-chip>
<input mdInput name="test" />
</md-chip-list>
<input mdInput name="test" [mdChipList]="chipList"/>
</md-input-container>
`
})
Expand Down
17 changes: 11 additions & 6 deletions src/lib/chips/chip-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
ChangeDetectionStrategy,
Component,
ContentChildren,
Directive,
Input,
QueryList,
ViewEncapsulation,
Expand All @@ -20,6 +21,14 @@ import {
} from '../core/keyboard/keycodes';
import {Dir} from '../core/rtl/dir';

@Directive({
selector: '[mdChipListContainer], [matChipListContainer]',
host: {
'[class.mat-chip-list-container]': 'true'
}
})
export class MdChipListContainer {}

/**
* A material design chips component (named ChipList for it's similarity to the List component).
*
Expand All @@ -39,7 +48,7 @@ import {Dir} from '../core/rtl/dir';
'[attr.tabindex]': '_tabIndex',
'role': 'listbox',
'[class.mat-chip-list]': 'true',

// Actions
'(focus)': 'focus($event)',
'(keydown)': '_keydown($event)'
},
Expand Down Expand Up @@ -118,17 +127,13 @@ export class MdChipList implements AfterContentInit, OnDestroy {
}
}

/**
* Associates an HTML input element with this chip list.
*
* @param inputElement The input to associate.
*/
@Input()
get selectable(): boolean { return this._selectable; }
set selectable(value: boolean) {
this._selectable = coerceBooleanProperty(value);
}

/** Associates an HTML input element with this chip list. */
registerInput(inputElement: HTMLInputElement) {
this._inputElement = inputElement;
}
Expand Down
8 changes: 4 additions & 4 deletions src/lib/chips/chip-remove.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ describe('Chip Remove', () => {
}));

describe('basic behavior', () => {
it('applies the `mat-chip-remove` CSS class', () => {
it('should applies the `mat-chip-remove` CSS class', () => {
let hrefElement = chipNativeElement.querySelector('a');

expect(hrefElement.classList).toContain('mat-chip-remove');
});

it('emits (remove) on click', () => {
it('should emits (remove) on click', () => {
let hrefElement = chipNativeElement.querySelector('a');

testChip.removable = true;
Expand All @@ -49,7 +49,7 @@ describe('Chip Remove', () => {
expect(testChip.didRemove).toHaveBeenCalled();
});

it(`monitors the parent chip's [removable] property`, () => {
it(`should monitors the parent chip's [removable] property`, () => {
let hrefElement = chipNativeElement.querySelector('a');

testChip.removable = true;
Expand All @@ -67,7 +67,7 @@ describe('Chip Remove', () => {

@Component({
template: `
<md-chip [removable]="removable" (remove)="didRemove()"><a md-chip-remove></a></md-chip>
<md-chip [removable]="removable" (remove)="didRemove()"><a mdChipRemove></a></md-chip>
`
})
class TestChip {
Expand Down
69 changes: 30 additions & 39 deletions src/lib/chips/chips.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,45 +19,33 @@ $mat-chip-remove-font-size: 18px;
flex-wrap: wrap;
align-items: flex-start;

/*
* Only apply the margins to chips
*/
.mat-chip:not(.mat-basic-chip) {
margin: $mat-chip-margin;

// Do not apply the special margins inside an input container
:not(.mat-input-wrapper) & {
// Remove the margin from the first element (in both LTR and RTL)
&:first-child {
margin: {
left: 0;
right: $mat-chip-margin;
}

[dir='rtl'] & {
margin: {
left: $mat-chip-margin;
right: 0;
}
}
// Remove the margin from the first element (in both LTR and RTL)
&:first-child {
margin-left: 0;
margin-right: $mat-chip-margin;

[dir='rtl'] & {
margin-right: 0;
margin-left: $mat-chip-margin;
}
}

// Remove the margin from the last element (in both LTR and RTL)
&:last-child {
margin-right: 0;
margin-left: $mat-chip-margin;

// Remove the margin from the last element (in both LTR and RTL)
&:last-child {
margin: {
left: $mat-chip-margin;
right: 0;
}

[dir='rtl'] & {
margin: {
left: 0;
right: $mat-chip-margin;
}
}
[dir='rtl'] & {
margin-left: 0;
margin-right: $mat-chip-margin;
}
}
}

}

.mat-input-prefix .mat-chip-list-wrapper {
Expand Down Expand Up @@ -87,15 +75,6 @@ $mat-chip-remove-font-size: 18px;
display: block;
margin: 0;
margin-bottom: $mat-chip-vertical-padding;

[dir='rtl'] & {
margin: 0;
margin-bottom: $mat-chip-vertical-padding;
}

&:last-child, [dir='rtl'] &:last-child {
margin-bottom: 0;
}
}
}

Expand All @@ -115,6 +94,18 @@ $mat-chip-remove-font-size: 18px;
display: none;
}

.mat-chip-list-container .mat-input-placeholder-wrapper {
top: -4px;

[dir='rtl'] & {
right: 8px;
}

[dir='ltr'] & {
margin-left: 8px;
}
}

.mat-chip-input {
[dir='rtl'] & {
margin-right: 8px;
Expand Down
10 changes: 3 additions & 7 deletions src/lib/chips/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {NgModule} from '@angular/core';
import {MdChipList} from './chip-list';
import {MdChipList, MdChipListContainer} from './chip-list';
import {MdChip} from './chip';
import {MdChipInput} from './chip-input';
import {MdChipRemove} from './chip-remove';
Expand All @@ -11,11 +11,7 @@ export * from './chip-remove';

@NgModule({
imports: [],
exports: [MdChipList, MdChip, MdChipInput, MdChipRemove],
declarations: [MdChipList, MdChip, MdChipInput, MdChipRemove]
exports: [MdChipList, MdChip, MdChipInput, MdChipRemove, MdChipListContainer],
declarations: [MdChipList, MdChip, MdChipInput, MdChipRemove, MdChipListContainer]
})
export class MdChipsModule {}


export * from './chip-list';
export * from './chip';

0 comments on commit afe6a4f

Please sign in to comment.