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

Commit d7c389d

Browse files
devversionThomasBurleson
authored andcommitted
fix(chips): do not trim the input model.
* The chips input should not trim the text, because otherwise the buffer will be always falsey, even when there are spaces in the input, and this would cause the backspace not to work. Fixes #7243 Closes #7748 # Conflicts: # src/components/chips/js/chipsController.js
1 parent b05b1f7 commit d7c389d

File tree

3 files changed

+114
-5
lines changed

3 files changed

+114
-5
lines changed

src/components/chips/chips.spec.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,59 @@ describe('<md-chips>', function() {
388388
expect(enterEvent.preventDefault).toHaveBeenCalled();
389389
}));
390390

391+
it('should trim the buffer when a chip will be added', inject(function($mdConstant) {
392+
var element = buildChips(BASIC_CHIP_TEMPLATE);
393+
var ctrl = element.controller('mdChips');
394+
var input = element.find('input');
395+
396+
// This string contains a lot of spaces, which should be trimmed.
397+
input.val(' Test ');
398+
input.triggerHandler('input');
399+
400+
expect(ctrl.chipBuffer).toBeTruthy();
401+
402+
var enterEvent = {
403+
type: 'keydown',
404+
keyCode: $mdConstant.KEY_CODE.ENTER,
405+
which: $mdConstant.KEY_CODE.ENTER
406+
};
407+
408+
input.triggerHandler(enterEvent);
409+
410+
expect(scope.items).toEqual(['Apple', 'Banana', 'Orange', 'Test']);
411+
}));
412+
413+
it('should not trim the input text of the input', inject(function($mdConstant) {
414+
var element = buildChips(BASIC_CHIP_TEMPLATE);
415+
var ctrl = element.controller('mdChips');
416+
var input = element.find('input');
417+
418+
input.val(' ');
419+
input.triggerHandler('input');
420+
421+
expect(ctrl.chipBuffer).toBeTruthy();
422+
423+
var enterEvent = {
424+
type: 'keydown',
425+
keyCode: $mdConstant.KEY_CODE.BACKSPACE,
426+
which: $mdConstant.KEY_CODE.BACKSPACE,
427+
preventDefault: jasmine.createSpy('preventDefault')
428+
};
429+
430+
input.triggerHandler(enterEvent);
431+
432+
expect(enterEvent.preventDefault).not.toHaveBeenCalled();
433+
434+
input.val('');
435+
input.triggerHandler('input');
436+
437+
input.triggerHandler(enterEvent);
438+
439+
expect(enterEvent.preventDefault).toHaveBeenCalledTimes(1);
440+
}));
391441
});
392442

443+
393444
it('focuses/blurs the component when focusing/blurring the input', inject(function() {
394445
var element = buildChips(BASIC_CHIP_TEMPLATE);
395446
var ctrl = element.controller('mdChips');

src/components/chips/js/chipsController.js

100755100644
Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ angular
1111
* @param $mdConstant
1212
* @param $log
1313
* @param $element
14+
* @param $mdUtil
1415
* @constructor
1516
*/
16-
function MdChipsCtrl ($scope, $mdConstant, $log, $element, $timeout) {
17+
function MdChipsCtrl ($scope, $mdConstant, $log, $element, $timeout, $mdUtil) {
1718
/** @type {$timeout} **/
1819
this.$timeout = $timeout;
1920

@@ -50,6 +51,8 @@ function MdChipsCtrl ($scope, $mdConstant, $log, $element, $timeout) {
5051
/** @type {boolean} */
5152
this.hasAutocomplete = false;
5253

54+
/** @type {string} */
55+
this.enableChipEdit = $mdUtil.parseAttributeBoolean(this.mdEnableChipEdit);
5356

5457
/**
5558
* Hidden hint text for how to delete a chip. Used to give context to screen readers.
@@ -137,18 +140,47 @@ MdChipsCtrl.prototype.inputKeydown = function(event) {
137140
if (this.separatorKeys.indexOf(event.keyCode) !== -1) {
138141
if ((this.hasAutocomplete && this.requireMatch) || !chipBuffer) return;
139142
event.preventDefault();
140-
this.appendChip(chipBuffer);
143+
144+
// Only append the chip and reset the chip buffer if the max chips limit isn't reached.
145+
if (this.hasMaxChipsReached()) return;
146+
147+
this.appendChip(chipBuffer.trim());
141148
this.resetChipBuffer();
142149
}
143150
};
144151

152+
153+
/**
154+
* Updates the content of the chip at given index
155+
* @param chipIndex
156+
* @param chipContents
157+
*/
158+
MdChipsCtrl.prototype.updateChipContents = function(chipIndex, chipContents){
159+
if(chipIndex >= 0 && chipIndex < this.items.length) {
160+
this.items[chipIndex] = chipContents;
161+
this.ngModelCtrl.$setDirty();
162+
}
163+
};
164+
165+
166+
/**
167+
* Returns true if a chip is currently being edited. False otherwise.
168+
* @return {boolean}
169+
*/
170+
MdChipsCtrl.prototype.isEditingChip = function(){
171+
return !!this.$element[0].getElementsByClassName('_md-chip-editing').length;
172+
};
173+
174+
145175
/**
146176
* Handles the keydown event on the chip elements: backspace removes the selected chip, arrow
147177
* keys switch which chips is active
148178
* @param event
149179
*/
150180
MdChipsCtrl.prototype.chipKeydown = function (event) {
151181
if (this.getChipBuffer()) return;
182+
if (this.isEditingChip()) return;
183+
152184
switch (event.keyCode) {
153185
case this.$mdConstant.KEY_CODE.BACKSPACE:
154186
case this.$mdConstant.KEY_CODE.DELETE:
@@ -242,7 +274,7 @@ MdChipsCtrl.prototype.appendChip = function(newChip) {
242274
var identical = this.items.some(function(item){
243275
return angular.equals(newChip, item);
244276
});
245-
if(identical) return;
277+
if (identical) return;
246278
}
247279

248280
// Check for a null (but not undefined), or existing chip and cancel appending
@@ -251,6 +283,10 @@ MdChipsCtrl.prototype.appendChip = function(newChip) {
251283
// Append the new chip onto our list
252284
var index = this.items.push(newChip);
253285

286+
// Update model validation
287+
this.ngModelCtrl.$setDirty();
288+
this.validateModel();
289+
254290
// If they provide the md-on-add attribute, notify them of the chip addition
255291
if (this.useOnAdd && this.onAdd) {
256292
this.onAdd({ '$chip': newChip, '$index': index });
@@ -350,13 +386,30 @@ MdChipsCtrl.prototype.resetChipBuffer = function() {
350386
}
351387
};
352388

389+
MdChipsCtrl.prototype.hasMaxChipsReached = function() {
390+
if (angular.isString(this.maxChips)) this.maxChips = parseInt(this.maxChips, 10) || 0;
391+
392+
return this.maxChips > 0 && this.items.length >= this.maxChips;
393+
};
394+
395+
/**
396+
* Updates the validity properties for the ngModel.
397+
*/
398+
MdChipsCtrl.prototype.validateModel = function() {
399+
this.ngModelCtrl.$setValidity('md-max-chips', !this.hasMaxChipsReached());
400+
};
401+
353402
/**
354403
* Removes the chip at the given index.
355404
* @param index
356405
*/
357406
MdChipsCtrl.prototype.removeChip = function(index) {
358407
var removed = this.items.splice(index, 1);
359408

409+
// Update model validation
410+
this.ngModelCtrl.$setDirty();
411+
this.validateModel();
412+
360413
if (removed && removed.length && this.useOnRemove && this.onRemove) {
361414
this.onRemove({ '$chip': removed[0], '$index': index });
362415
}
@@ -415,7 +468,7 @@ MdChipsCtrl.prototype.selectAndFocusChip = function(index) {
415468
* Call `focus()` on the chip at `index`
416469
*/
417470
MdChipsCtrl.prototype.focusChip = function(index) {
418-
this.$element[0].querySelector('md-chip[index="' + index + '"] .md-chip-content').focus();
471+
this.$element[0].querySelector('md-chip[index="' + index + '"] ._md-chip-content').focus();
419472
};
420473

421474
/**
@@ -479,10 +532,14 @@ MdChipsCtrl.prototype.configureUserInput = function(inputElement) {
479532
};
480533

481534
MdChipsCtrl.prototype.configureAutocomplete = function(ctrl) {
482-
if ( ctrl ){
535+
if ( ctrl ) {
483536
this.hasAutocomplete = true;
537+
484538
ctrl.registerSelectedItemWatcher(angular.bind(this, function (item) {
485539
if (item) {
540+
// Only append the chip and reset the chip buffer if the max chips limit isn't reached.
541+
if (this.hasMaxChipsReached()) return;
542+
486543
this.appendChip(item);
487544
this.resetChipBuffer();
488545
}

src/components/chips/js/chipsDirective.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@
131131
ng-model="$mdChipsCtrl.chipBuffer"\
132132
ng-focus="$mdChipsCtrl.onInputFocus()"\
133133
ng-blur="$mdChipsCtrl.onInputBlur()"\
134+
ng-trim="false"\
134135
ng-keydown="$mdChipsCtrl.inputKeydown($event)">';
135136

136137
var CHIP_DEFAULT_TEMPLATE = '\

0 commit comments

Comments
 (0)