Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit 333984f

Browse files
topherfangioThomasBurleson
authored andcommitted
feat(mdChips): Add md-on-select expression support.
Users want a way to be notified when a chip is selected. fix #3413. closes #4088.
1 parent 33815a7 commit 333984f

File tree

3 files changed

+65
-19
lines changed

3 files changed

+65
-19
lines changed

src/components/chips/chips.spec.js

+20-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ describe('<md-chips>', function() {
66
'<md-chips ng-model="items" md-on-append="appendChip($chip)"></md-chips>';
77
var CHIP_REMOVE_TEMPLATE =
88
'<md-chips ng-model="items" md-on-remove="removeChip($chip, $index)"></md-chips>';
9+
var CHIP_SELECT_TEMPLATE =
10+
'<md-chips ng-model="items" md-on-select="selectChip($chip)"></md-chips>';
911
var CHIP_READONLY_AUTOCOMPLETE_TEMPLATE =
1012
'<md-chips ng-model="items" readonly="true">' +
1113
' <md-autocomplete md-items="item in [\'hi\', \'ho\', \'he\']"></md-autocomplete>' +
@@ -134,6 +136,21 @@ describe('<md-chips>', function() {
134136
});
135137

136138

139+
it('should call the select method when selecting a chip', function() {
140+
var element = buildChips(CHIP_SELECT_TEMPLATE);
141+
var ctrl = element.controller('mdChips');
142+
143+
scope.selectChip = jasmine.createSpy('selectChip');
144+
145+
element.scope().$apply(function() {
146+
ctrl.items = ['Grape'];
147+
ctrl.selectChip(0);
148+
});
149+
150+
expect(scope.selectChip).toHaveBeenCalled();
151+
expect(scope.selectChip.calls.mostRecent().args[0]).toBe('Grape');
152+
});
153+
137154
it('should handle appending an object chip', function() {
138155
var element = buildChips(CHIP_APPEND_TEMPLATE);
139156
var ctrl = element.controller('mdChips');
@@ -394,9 +411,9 @@ describe('<md-chips>', function() {
394411
});
395412
});
396413

397-
// *******************************
398-
// Internal helper methods
399-
// *******************************
414+
// *******************************
415+
// Internal helper methods
416+
// *******************************
400417

401418
function buildChips(str) {
402419
var container;

src/components/chips/js/chipsController.js

+35-12
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,18 @@ function MdChipsCtrl ($scope, $mdConstant, $log, $element, $timeout) {
6767
this.chipBuffer = '';
6868

6969
/**
70-
* Whether to use the mdOnAppend expression to transform the chip buffer
70+
* Whether to use the onAppend expression to transform the chip buffer
7171
* before appending it to the list.
7272
* @type {boolean}
7373
*/
74-
this.useMdOnAppend = false;
74+
this.useOnAppend = false;
75+
76+
/**
77+
* Whether to use the onSelect expression to notify the component's user
78+
* after selecting a chip from the list.
79+
* @type {boolean}
80+
*/
81+
this.useOnSelect = false;
7582
}
7683

7784
/**
@@ -181,8 +188,8 @@ MdChipsCtrl.prototype.getAdjacentChipIndex = function(index) {
181188
* @param newChip
182189
*/
183190
MdChipsCtrl.prototype.appendChip = function(newChip) {
184-
if (this.useMdOnAppend && this.mdOnAppend) {
185-
newChip = this.mdOnAppend({'$chip': newChip});
191+
if (this.useOnAppend && this.onAppend) {
192+
newChip = this.onAppend({'$chip': newChip});
186193
}
187194
if (this.items.indexOf(newChip) + 1) return;
188195
this.items.push(newChip);
@@ -191,23 +198,34 @@ MdChipsCtrl.prototype.appendChip = function(newChip) {
191198
/**
192199
* Sets whether to use the md-on-append expression. This expression is
193200
* bound to scope and controller in {@code MdChipsDirective} as
194-
* {@code mdOnAppend}. Due to the nature of directive scope bindings, the
201+
* {@code onAppend}. Due to the nature of directive scope bindings, the
195202
* controller cannot know on its own/from the scope whether an expression was
196203
* actually provided.
197204
*/
198-
MdChipsCtrl.prototype.useMdOnAppendExpression = function() {
199-
this.useMdOnAppend = true;
205+
MdChipsCtrl.prototype.useOnAppendExpression = function() {
206+
this.useOnAppend = true;
200207
};
201208

202209
/**
203210
* Sets whether to use the md-on-remove expression. This expression is
204211
* bound to scope and controller in {@code MdChipsDirective} as
205-
* {@code mdOnRemove}. Due to the nature of directive scope bindings, the
212+
* {@code onRemove}. Due to the nature of directive scope bindings, the
213+
* controller cannot know on its own/from the scope whether an expression was
214+
* actually provided.
215+
*/
216+
MdChipsCtrl.prototype.useOnRemoveExpression = function() {
217+
this.useOnRemove = true;
218+
};
219+
220+
/*
221+
* Sets whether to use the md-on-select expression. This expression is
222+
* bound to scope and controller in {@code MdChipsDirective} as
223+
* {@code onSelect}. Due to the nature of directive scope bindings, the
206224
* controller cannot know on its own/from the scope whether an expression was
207225
* actually provided.
208226
*/
209-
MdChipsCtrl.prototype.useMdOnRemoveExpression = function() {
210-
this.useMdOnRemove = true;
227+
MdChipsCtrl.prototype.useOnSelectExpression = function() {
228+
this.useOnSelect = true;
211229
};
212230

213231
/**
@@ -247,8 +265,8 @@ MdChipsCtrl.prototype.resetChipBuffer = function() {
247265
MdChipsCtrl.prototype.removeChip = function(index) {
248266
var removed = this.items.splice(index, 1);
249267

250-
if (removed && removed.length && this.useMdOnRemove && this.mdOnRemove) {
251-
this.mdOnRemove({ '$chip': removed[0], '$index': index });
268+
if (removed && removed.length && this.useOnRemove && this.onRemove) {
269+
this.onRemove({ '$chip': removed[0], '$index': index });
252270
}
253271
};
254272

@@ -280,6 +298,11 @@ MdChipsCtrl.prototype.selectAndFocusChipSafe = function(index) {
280298
MdChipsCtrl.prototype.selectChip = function(index) {
281299
if (index >= -1 && index <= this.items.length) {
282300
this.selectedChip = index;
301+
302+
// Fire the onSelect if provided
303+
if (this.useOnSelect && this.onSelect) {
304+
this.onSelect({'$chip': this.items[this.selectedChip] });
305+
}
283306
} else {
284307
this.$log.warn('Selected Chip index out of bounds; ignoring.');
285308
}

src/components/chips/js/chipsDirective.js

+10-4
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
* object when adding a chip.
6969
* @param {expression} md-on-remove An expression which will be called when a chip has been
7070
* removed.
71+
* @param {expression} md-on-select An expression which will be called when a chip is selected.
7172
* @param {string=} delete-hint A string read by screen readers instructing users that pressing
7273
* the delete key will remove the chip.
7374
* @param {string=} delete-button-label A label for the delete button. Also hidden and read by
@@ -162,8 +163,9 @@
162163
readonly: '=readonly',
163164
placeholder: '@',
164165
secondaryPlaceholder: '@',
165-
mdOnAppend: '&',
166-
mdOnRemove: '&',
166+
onAppend: '&mdOnAppend',
167+
onRemove: '&mdOnRemove',
168+
onSelect: '&mdOnSelect',
167169
deleteHint: '@',
168170
deleteButtonLabel: '@',
169171
requireMatch: '=?mdRequireMatch'
@@ -245,11 +247,15 @@
245247

246248
// If an `md-on-append` attribute was set, tell the controller to use the expression
247249
// when appending chips.
248-
if (attrs.mdOnAppend) mdChipsCtrl.useMdOnAppendExpression();
250+
if (attrs.mdOnAppend) mdChipsCtrl.useOnAppendExpression();
249251

250252
// If an `md-on-remove` attribute was set, tell the controller to use the expression
251253
// when removing chips.
252-
if (attrs.mdOnRemove) mdChipsCtrl.useMdOnRemoveExpression();
254+
if (attrs.mdOnRemove) mdChipsCtrl.useOnRemoveExpression();
255+
256+
// If an `md-on-select` attribute was set, tell the controller to use the expression
257+
// when selecting chips.
258+
if (attrs.mdOnSelect) mdChipsCtrl.useOnSelectExpression();
253259

254260
// The md-autocomplete and input elements won't be compiled until after this directive
255261
// is complete (due to their nested nature). Wait a tick before looking for them to

0 commit comments

Comments
 (0)