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

Commit

Permalink
Merge 3405b70 into f1f5124
Browse files Browse the repository at this point in the history
  • Loading branch information
dlukez committed Mar 9, 2015
2 parents f1f5124 + 3405b70 commit 28f817e
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 9 deletions.
18 changes: 12 additions & 6 deletions src/auto-complete.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* @param {expression} source Expression to evaluate upon changing the input content. The input value is available as
* $query. The result of the expression must be a promise that eventually resolves to an
* array of strings.
* @param {string=} [displayProperty=text] Property to be rendered as the autocomplete label.
* @param {number=} [debounceDelay=100] Amount of time, in milliseconds, to wait before evaluating the expression in
* the source option after the last keystroke.
* @param {number=} [minLength=3] Minimum number of characters that must be entered before evaluating the expression
Expand All @@ -30,11 +31,15 @@
*/
tagsInput.directive('autoComplete', function($document, $timeout, $sce, $q, tagsInputConfig, tiUtil) {
function SuggestionList(loadFn, options) {
var self = {}, getDifference, lastPromise;
var self = {}, getDifference, lastPromise, getIdProperty;

getIdProperty = function() {
return options.tagsInput.keyProperty || options.displayProperty || options.tagsInput.displayProperty;
};

getDifference = function(array1, array2) {
return array1.filter(function(item) {
return !tiUtil.findInObjectArray(array2, item, options.tagsInput.displayProperty);
return !tiUtil.findInObjectArray(array2, item, getIdProperty());
});
};

Expand Down Expand Up @@ -67,7 +72,7 @@ tagsInput.directive('autoComplete', function($document, $timeout, $sce, $q, tags
return;
}

items = tiUtil.makeObjectArray(items.data || items, options.tagsInput.displayProperty);
items = tiUtil.makeObjectArray(items.data || items, getIdProperty());
items = getDifference(items, tags);
self.items = items.slice(0, options.maxResultsToShow);

Expand Down Expand Up @@ -119,7 +124,8 @@ tagsInput.directive('autoComplete', function($document, $timeout, $sce, $q, tags
loadOnDownArrow: [Boolean, false],
loadOnEmpty: [Boolean, false],
loadOnFocus: [Boolean, false],
selectFirstMatch: [Boolean, true]
selectFirstMatch: [Boolean, true],
displayProperty: [String, '']
});

options = scope.options;
Expand All @@ -130,7 +136,7 @@ tagsInput.directive('autoComplete', function($document, $timeout, $sce, $q, tags
suggestionList = new SuggestionList(scope.source, options);

getItem = function(item) {
return item[options.tagsInput.displayProperty];
return item[options.displayProperty || options.tagsInput.displayProperty];
};

getDisplayText = function(item) {
Expand Down Expand Up @@ -171,7 +177,7 @@ tagsInput.directive('autoComplete', function($document, $timeout, $sce, $q, tags
};

scope.track = function(item) {
return getItem(item);
return options.tagsInput.keyProperty ? item[options.tagsInput.keyProperty] : getItem(item);
};

tagsInput
Expand Down
12 changes: 9 additions & 3 deletions src/tags-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} [displayProperty=text] Property to be rendered as the tag label.
* @param {string=} [keyProperty=text] Property to be used for tracking items in the ng-repeat.
* @param {string=} [type=text] Type of the input element. Only 'text', 'email' and 'url' are supported values.
* @param {number=} tabindex Tab order of the control.
* @param {string=} [placeholder=Add a tag] Placeholder text for the control.
Expand Down Expand Up @@ -41,7 +42,11 @@
*/
tagsInput.directive('tagsInput', function($timeout, $document, tagsInputConfig, tiUtil) {
function TagList(options, events) {
var self = {}, getTagText, setTagText, tagIsValid;
var self = {}, getTagText, setTagText, tagIsValid, getIdProperty;

getIdProperty = function() {
return options.keyProperty || options.displayProperty;
};

getTagText = function(tag) {
return tiUtil.safeToString(tag[options.displayProperty]);
Expand All @@ -58,7 +63,7 @@ tagsInput.directive('tagsInput', function($timeout, $document, tagsInputConfig,
tagText.length >= options.minLength &&
tagText.length <= options.maxLength &&
options.allowedTagsPattern.test(tagText) &&
!tiUtil.findInObjectArray(self.items, tag, options.displayProperty);
!tiUtil.findInObjectArray(self.items, tag, getIdProperty());
};

self.items = [];
Expand Down Expand Up @@ -150,6 +155,7 @@ tagsInput.directive('tagsInput', function($timeout, $document, tagsInputConfig,
minTags: [Number, 0],
maxTags: [Number, MAX_SAFE_INTEGER],
displayProperty: [String, 'text'],
keyProperty: [String, ''],
allowLeftoverText: [Boolean, false],
addFromAutocompleteOnly: [Boolean, false],
spellcheck: [Boolean, true]
Expand Down Expand Up @@ -212,7 +218,7 @@ tagsInput.directive('tagsInput', function($timeout, $document, tagsInputConfig,
};

scope.track = function(tag) {
return tag[options.displayProperty];
return tag[options.keyProperty || options.displayProperty];
};

scope.$watch('tags', function(value) {
Expand Down
28 changes: 28 additions & 0 deletions test/auto-complete.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1088,4 +1088,32 @@ describe('autoComplete directive', function() {

});
});

describe('display-property option', function() {
it('initializes the option to ""', function() {
// Arrange/Act
compile();

// Assert
expect(isolateScope.options.displayProperty).toBe('');
});

it('renders the correct display text', function() {
// Arrange
compile('display-property="label"');

// Act
loadSuggestions([
{ label: 'Item1' },
{ label: 'Item2' },
{ label: 'Item3' }
]);

// Assert
expect(getSuggestions().length).toBe(3);
expect(getSuggestionText(0)).toBe('Item1');
expect(getSuggestionText(1)).toBe('Item2');
expect(getSuggestionText(2)).toBe('Item3');
});
});
});
58 changes: 58 additions & 0 deletions test/tags-input.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1205,7 +1205,65 @@ describe('tags-input directive', function() {
{ label: 'Item3' }
]);
});
});

describe('key-property option', function () {
it('initializes the option to ""', function () {
// Arrange/Act
compile();

// Assert
expect(isolateScope.options.keyProperty).toBe('');
});

it('allows settings tags with duplicate labels', function () {
// Arrange
$scope.tags= [
{ id: 1, text: 'Tag' },
{ id: 2, text: 'Tag' }
];

// Act
compile('key-property="id"');

// Assert
// no exception
});

it('allows tracking tags by a custom property', function () {
// Arrange
$scope.tags = [
{ id: 1, text: 'Tag' }
];
compile('key-property="id"');

// Act
isolateScope.tagList.add({ id: 2, text: 'Tag' });

// Assert
expect(isolateScope.newTag.invalid).toBeFalsy();
expect($scope.tags).toEqual([
{ id: 1, text: 'Tag' },
{ id: 2, text: 'Tag' }
]);
});

it('fails with duplicate track properties', function () {
// Arrange
$scope.tags = [
{ id: 1, text: 'Tag' }
];
compile('key-property="id"');

// Act
isolateScope.tagList.add({ id: 1, text: 'Other' });

// Assert
expect(isolateScope.newTag.invalid).toBeTruthy();
expect($scope.tags).toEqual([
{ id: 1, text: 'Tag' }
]);
});
});

describe('allow-leftover-text option', function() {
Expand Down
33 changes: 33 additions & 0 deletions test/test-page.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@
$digest: <span class="digest-length"></span>ms
</div>


<p></p>
Track-property and overwritten display-property for auto-complete (search for Dan)
<tags-input ng-model="empTags" key-property="email" display-property="name">
<auto-complete source="loadEmps($query)" load-on-down-arrow="true" display-property="email" min-length="1"></auto-complete>
</tags-input>

<script type="text/javascript">
angular.module('app', ['ngTagsInput', 'angularStats'])
.controller('Ctrl', function($scope, $q) {
Expand Down Expand Up @@ -57,6 +64,32 @@
deferred.resolve(items);
return deferred.promise;
};

var emps = [
{ name: 'Dan', email: 'dan@test.com' },
{ name: 'George', email: 'george@test.com' },
{ name: 'Christina', email: 'christina@test.com' },
{ name: 'Sally', email: 'sally@test.com' },
{ name: 'Dan', email: 'dan2@test.com' },
{ name: 'Steph', email: 'steph@test.com' },
{ name: 'Bob', email: 'bob@test.com' },
{ name: 'Sebastian', email: 'sebastian@test.com' }
];

$scope.empTags = [emps[0], emps[3], emps[5]];

$scope.loadEmps = function(query) {
var deferred = $q.defer();
var items = [];
for (var i = 0; i < emps.length; i++) {
if (emps[i].name.toLowerCase().indexOf(query.toLowerCase()) > -1) {
items.push(emps[i]);
}
}
deferred.resolve(items);
return deferred.promise;
};

$scope.focus = function() {
console.log('focus');
};
Expand Down

0 comments on commit 28f817e

Please sign in to comment.