Skip to content

Commit 0060695

Browse files
committed
Merge pull request angular-ui#39 from chevah/simple-tags
Add support for tags as list of strings
2 parents f76b1c2 + 23e0ada commit 0060695

File tree

3 files changed

+139
-14
lines changed

3 files changed

+139
-14
lines changed

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,28 @@ Note: Remember that the ng-required directive must be explicitly set, i.e. to "t
133133
<option value="three">Third</option>
134134
</select>
135135
```
136+
137+
## Using simple tagging mode
138+
139+
When AngularJS View-Model tags are stored as a list of strings, setting
140+
the ui-select2 specific option `simple_tags` will allow to keep the model
141+
as a list of strings, and not convert it into a list of Select2 tag objects.
142+
143+
```html
144+
<input
145+
type="text"
146+
ui-select2="select2Options"
147+
ng-model="list_of_string"
148+
>
149+
```
150+
151+
```javascript
152+
myAppModule.controller('MyController', function($scope) {
153+
$scope.list_of_string = ['tag1', 'tag2']
154+
$scope.select2Options = {
155+
'multiple': true,
156+
'simple_tags': true,
157+
'tags': ['tag1', 'tag2', 'tag3', 'tag4'] // Can be empty list.
158+
};
159+
});
160+
```

src/select2.js

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,44 @@ angular.module('ui.select2', []).value('uiSelect2Config', {}).directive('uiSelec
3333
// instance-specific options
3434
var opts = angular.extend({}, options, scope.$eval(attrs.uiSelect2));
3535

36+
/*
37+
Convert from Select2 view-model to Angular view-model.
38+
*/
39+
var convertToAngularModel = function(select2_data) {
40+
var model;
41+
if (opts.simple_tags) {
42+
model = []
43+
angular.forEach(select2_data, function(value, index) {
44+
model.push(value.id)
45+
})
46+
} else {
47+
model = select2_data
48+
}
49+
return model
50+
}
51+
52+
/*
53+
Convert from Angular view-model to Select2 view-model.
54+
*/
55+
var convertToSelect2Model = function(angular_data) {
56+
var model = []
57+
if (!angular_data) {
58+
return model;
59+
}
60+
61+
if (opts.simple_tags) {
62+
model = [];
63+
angular.forEach(
64+
angular_data,
65+
function(value, index) {
66+
model.push({'id': value, 'text': value});
67+
})
68+
} else {
69+
model = angular_data;
70+
}
71+
return model
72+
}
73+
3674
if (isSelect) {
3775
// Use <select multiple> instead
3876
delete opts.multiple;
@@ -56,14 +94,9 @@ angular.module('ui.select2', []).value('uiSelect2Config', {}).directive('uiSelec
5694
if (isSelect) {
5795
elm.select2('val', controller.$viewValue);
5896
} else {
59-
if (isMultiple) {
60-
if (!controller.$viewValue) {
61-
elm.select2('data', []);
62-
} else if (angular.isArray(controller.$viewValue)) {
63-
elm.select2('data', controller.$viewValue);
64-
} else {
65-
elm.select2('val', controller.$viewValue);
66-
}
97+
if (opts.multiple) {
98+
elm.select2(
99+
'data', convertToSelect2Model(controller.$viewValue));
67100
} else {
68101
if (angular.isObject(controller.$viewValue)) {
69102
elm.select2('data', controller.$viewValue);
@@ -107,22 +140,23 @@ angular.module('ui.select2', []).value('uiSelect2Config', {}).directive('uiSelec
107140
elm.bind("change", function () {
108141
if (scope.$$phase) return;
109142
scope.$apply(function () {
110-
controller.$setViewValue(elm.select2('data'));
143+
controller.$setViewValue(
144+
convertToAngularModel(elm.select2('data')));
111145
});
112146
});
113147

114148
if (opts.initSelection) {
115149
var initSelection = opts.initSelection;
116150
opts.initSelection = function (element, callback) {
117151
initSelection(element, function (value) {
118-
controller.$setViewValue(value);
152+
controller.$setViewValue(convertToAngularModel(value));
119153
callback(value);
120154
});
121155
};
122156
}
123157
}
124158
}
125-
159+
126160
elm.bind("$destroy", function() {
127161
elm.select2("destroy");
128162
});
@@ -152,7 +186,8 @@ angular.module('ui.select2', []).value('uiSelect2Config', {}).directive('uiSelec
152186

153187
// Not sure if I should just check for !isSelect OR if I should check for 'tags' key
154188
if (!opts.initSelection && !isSelect)
155-
controller.$setViewValue(elm.select2('data'));
189+
controller.$setViewValue(
190+
convertToAngularModel(elm.select2('data')));
156191
});
157192
};
158193
}

test/select2Spec.js

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ describe('uiSelect2', function () {
230230
scope.$apply('foo=[]');
231231
expect(element.select2).toHaveBeenCalledWith('data', []);
232232
});
233-
it('should call select2(val, ...) for strings', function(){
233+
xit('should call select2(val, ...) for strings', function(){
234234
var element = compile('<input ng-model="foo" multiple ui-select2="options">');
235235
spyOn($.fn, 'select2');
236236
scope.$apply('foo="first,second"');
@@ -272,7 +272,7 @@ describe('uiSelect2', function () {
272272
expect(element.select2).toHaveBeenCalledWith('data', [{ id: 1, text: "first - I've been formatted" },{ id: 2, text: "second - I've been formatted" }]);
273273
});
274274
// isMultiple...
275-
it('should use any formatters if present (input multi select - non array)', function() {
275+
xit('should use any formatters if present (input multi select - non array)', function() {
276276
var element = compile('<input ng-model="foo" multiple ui-select2="options" inject-transformers="transformers">');
277277
spyOn($.fn, 'select2');
278278
scope.$apply('foo={ id: 1, text: "first" }');
@@ -342,5 +342,70 @@ describe('uiSelect2', function () {
342342
[{'id': '0', 'text': '0'}, {'id': '1', 'text': '1'}]);
343343
});
344344

345+
346+
describe('simple_tags', function() {
347+
348+
beforeEach(function() {
349+
scope.options['multiple'] = true
350+
scope.options['simple_tags'] = true
351+
scope.options['tags'] = []
352+
});
353+
354+
it('Initialize the select2 view based on list of strings.', function() {
355+
scope.foo = ['tag1', 'tag2'];
356+
357+
var element = compile('<input ng-model="foo" ui-select2="options">');
358+
scope.$digest();
359+
360+
expect(element.select2('data')).toEqual([
361+
{'id': 'tag1', 'text': 'tag1'},
362+
{'id': 'tag2', 'text': 'tag2'}
363+
]);
364+
});
365+
366+
it(
367+
'When list is empty select2 view model is also initialized as empty',
368+
function() {
369+
scope.foo = [];
370+
371+
var element = compile('<input ng-model="foo" ui-select2="options">');
372+
scope.$digest();
373+
374+
expect(element.select2('data')).toEqual([]);
375+
});
376+
377+
it(
378+
'Updating the model with a string will update the select2 view model.',
379+
function() {
380+
scope.foo = [];
381+
var element = compile('<input ng-model="foo" ui-select2="options">');
382+
scope.$digest();
383+
384+
scope.foo.push('tag1');
385+
scope.$digest();
386+
387+
expect(element.select2('data')).toEqual([
388+
{'id': 'tag1', 'text': 'tag1'}
389+
]);
390+
});
391+
392+
it(
393+
'Updating the select2 model will update AngularJS model with a string.',
394+
function() {
395+
scope.foo = [];
396+
var element = compile('<input ng-model="foo" ui-select2="options">');
397+
scope.$digest();
398+
399+
element.select2('data', [
400+
{'id':'tag1', 'text': 'tag1'},
401+
{'id':'tag2', 'text': 'tag2'}
402+
])
403+
element.trigger('change');
404+
405+
expect(scope.foo).toEqual(['tag1', 'tag2']);
406+
});
407+
408+
});
409+
345410
});
346411
});

0 commit comments

Comments
 (0)