Skip to content
This repository has been archived by the owner on Nov 22, 2021. It is now read-only.

Fix "on-" callback issues when using use-strings="true" #875

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 19 additions & 10 deletions src/tags-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,11 @@ export default function TagsInputDirective($timeout, $document, $window, $q, tag
return canAddTag(tag)
.then(() =>{
self.items.push(tag);
events.trigger('tag-added', { $tag: tag });
events.trigger('tag-added', { $tag: options.useStrings ? getTagText(tag) : tag });
})
.catch(() => {
if (tagText) {
events.trigger('invalid-tag', { $tag: tag });
events.trigger('invalid-tag', { $tag: options.useStrings ? getTagText(tag) : tag });
}
});
};
Expand All @@ -111,7 +111,7 @@ export default function TagsInputDirective($timeout, $document, $window, $q, tag
return canRemoveTag(tag).then(() => {
self.items.splice(index, 1);
self.clearSelection();
events.trigger('tag-removed', { $tag: tag });
events.trigger('tag-removed', { $tag: options.useStrings ? getTagText(tag) : tag });
return tag;
});
};
Expand Down Expand Up @@ -143,7 +143,7 @@ export default function TagsInputDirective($timeout, $document, $window, $q, tag
self.index = -1;
};

self.getItems = () => options.useStrings ? self.items.map(getTagText) : self.items;
self.getItems = () => options.useStrings ? self.items.map(getTagText) : self.items.slice();

self.clearSelection();

Expand Down Expand Up @@ -286,7 +286,7 @@ export default function TagsInputDirective($timeout, $document, $window, $q, tag
];
};

scope.$watch('tags', value => {
scope.$watchCollection('tags', value => {
if (value) {
tagList.items = tiUtil.makeObjectArray(value, options.displayProperty);
if (options.useStrings) {
Expand Down Expand Up @@ -361,15 +361,24 @@ export default function TagsInputDirective($timeout, $document, $window, $q, tag
};

events
.on('tag-added', scope.onTagAdded)
.on('invalid-tag', scope.onInvalidTag)
.on('tag-removed', scope.onTagRemoved)
.on('tag-clicked', scope.onTagClicked)
.on('tag-added', function($tag) { $timeout(function() { scope.onTagAdded($tag); }); })
.on('invalid-tag', function($tag) { $timeout(function() { scope.onInvalidTag($tag); }); })
.on('tag-removed', function($tag) { $timeout(function() { scope.onTagRemoved($tag); }); })
.on('tag-clicked', function($tag) { $timeout(function() { scope.onTagClicked($tag); }); })
.on('tag-added', () => {
scope.newTag.text('');
})
.on('tag-added tag-removed', () => {
scope.tags = tagList.getItems();
var items = tagList.getItems();

if(!scope.tags) {
scope.tags = [];
} else {
scope.tags.length = 0;
}

Array.prototype.push.apply(scope.tags, items);

// Ideally we should be able call $setViewValue here and let it in turn call $setDirty and $validate
// automatically, but since the model is an array, $setViewValue does nothing and it's up to us to do it.
// Unfortunately this won't trigger any registered $parser and there's no safe way to do it.
Expand Down
74 changes: 66 additions & 8 deletions test/tags-input.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1749,7 +1749,9 @@ describe('tags-input directive', () => {
newTag('foo');

// Assert
expect($scope.callback).toHaveBeenCalledWith({ text: 'foo' });
$timeout(function() {
expect($scope.callback).toHaveBeenCalledWith({ text: 'foo' });
});
});
});

Expand All @@ -1763,7 +1765,9 @@ describe('tags-input directive', () => {
newTag('foo');

// Assert
expect($scope.callback).toHaveBeenCalledWith({ text: 'foo' });
$timeout(function() {
expect($scope.callback).toHaveBeenCalledWith({ text: 'foo' });
});
});
});

Expand All @@ -1784,7 +1788,9 @@ describe('tags-input directive', () => {
getRemoveButton(0).click();

// Assert
expect($scope.tags).toEqual([{ text: 'PERMANENT' }]);
$timeout(function() {
expect($scope.tags).toEqual([{ text: 'PERMANENT' }]);
});
});

it('removes a tag if the on-tag-removing callback allows it (promise result)', () => {
Expand All @@ -1801,7 +1807,9 @@ describe('tags-input directive', () => {
getRemoveButton(1).click();

// Assert
expect($scope.tags).toEqual([{ text: 'foo' }, { text: 'PERMANENT' }, { text: 'bar' }]);
$timeout(function() {
expect($scope.tags).toEqual([{ text: 'foo' }, { text: 'PERMANENT' }, { text: 'bar' }]);
});
});
});

Expand All @@ -1816,7 +1824,9 @@ describe('tags-input directive', () => {
getRemoveButton(0).click();

// Assert
expect($scope.callback).toHaveBeenCalledWith({ text: 'Tag1' });
$timeout(function() {
expect($scope.callback).toHaveBeenCalledWith({ text: 'Tag1' });
});
});

it('calls the provided callback when the last tag is removed by pressing backspace twice', () => {
Expand All @@ -1830,7 +1840,9 @@ describe('tags-input directive', () => {
sendBackspace();

// Assert
expect($scope.callback).toHaveBeenCalledWith({ text: 'Tag2' });
$timeout(function() {
expect($scope.callback).toHaveBeenCalledWith({ text: 'Tag2' });
});
});
});

Expand All @@ -1845,7 +1857,9 @@ describe('tags-input directive', () => {
getTag(1).click();

// Assert
expect($scope.callback).toHaveBeenCalledWith({ text: 'Tag2' });
$timeout(function() {
expect($scope.callback).toHaveBeenCalledWith({ text: 'Tag2' });
});
});

it('doesn\'t call the provided callback when the remove button is clicked', () => {
Expand All @@ -1858,7 +1872,9 @@ describe('tags-input directive', () => {
getRemoveButton(1).click();

// Assert
expect($scope.callback).not.toHaveBeenCalled();
$timeout(function() {
expect($scope.callback).not.toHaveBeenCalled();
});
});
});

Expand Down Expand Up @@ -1961,6 +1977,48 @@ describe('tags-input directive', () => {
expect(getTagText(1)).toBe('Tag2');
expect(getTagText(2)).toBe('Tag3');
});

it('calls the provided callback with just tag name when a new tag is added', () => {
// Arrange
$scope.callback = jasmine.createSpy();
compile('use-strings="true" on-tag-added="callback($tag)"');

// Act
newTag('foo');

// Assert
$timeout(function() {
expect($scope.callback).toHaveBeenCalledWith('foo');
});
});

it('calls the provided callback when a tag is removed by clicking the remove button', () => {
// Arrange
$scope.callback = jasmine.createSpy();
compile('use-strings="true" on-tag-removed="callback($tag)"');

// Act
getRemoveButton(0).click();

// Assert
$timeout(function() {
expect($scope.callback).toHaveBeenCalledWith('Tag1');
});
});

it('calls the provided callback when a tag is clicked', () => {
// Arrange
$scope.callback = jasmine.createSpy();
compile('use-strings="true" on-tag-clicked="callback($tag)"');

// Act
getTag(1).click();

// Assert
$timeout(function() {
expect($scope.callback).toHaveBeenCalledWith('Tag2');
});
});
});

describe('ng-disabled support', () => {
Expand Down