Skip to content
This repository was archived by the owner on Oct 2, 2019. It is now read-only.

Commit ce7e668

Browse files
committed
feat(templates): Let user define disabling expression.
1 parent 5d0a4e6 commit ce7e668

File tree

2 files changed

+140
-21
lines changed

2 files changed

+140
-21
lines changed

src/select.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
ctrl.searchEnabled = undefined; // Initialized inside uiSelect directive link function
112112
ctrl.resetSearchInput = undefined; // Initialized inside uiSelect directive link function
113113
ctrl.refreshDelay = undefined; // Initialized inside uiSelectChoices directive link function
114+
ctrl.disableChoiceExpression = undefined;
114115

115116
ctrl.isEmpty = function() {
116117
return angular.isUndefined(ctrl.selected) || ctrl.selected === null || ctrl.selected === '';
@@ -234,9 +235,10 @@
234235
var isDisabled = false;
235236
var item;
236237

237-
if (itemIndex >= 0) {
238+
if (itemIndex >= 0 && !angular.isUndefined(ctrl.disableChoiceExpression)) {
238239
item = ctrl.items[itemIndex];
239-
isDisabled = item.disabled;
240+
isDisabled = !!(itemScope.$eval(ctrl.disableChoiceExpression)); // force the boolean value
241+
item._uiSelectChoiceDisabled = isDisabled; // store this for later reference
240242
}
241243

242244
return isDisabled;
@@ -245,7 +247,7 @@
245247
// When the user clicks on an item inside the dropdown
246248
ctrl.select = function(item) {
247249

248-
if (!item.disabled) {
250+
if (!item._uiSelectChoiceDisabled) {
249251
var locals = {};
250252
locals[ctrl.parserResult.itemName] = item;
251253

@@ -606,6 +608,8 @@
606608

607609
$select.parseRepeatAttr(attrs.repeat, groupByExp); //Result ready at $select.parserResult
608610

611+
$select.disableChoiceExpression = attrs.uiDisableChoice;
612+
609613
if(groupByExp) {
610614
var groups = element.querySelectorAll('.ui-select-choices-group');
611615
if (groups.length !== 1) throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-group but got '{0}'.", groups.length);

test/select.spec.js

Lines changed: 133 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -207,45 +207,160 @@ describe('ui-select tests', function() {
207207
});
208208

209209
describe('disabled options', function() {
210-
function createUiSelect() {
210+
function createUiSelect(attrs) {
211+
var attrsDisabled = '';
212+
if (attrs !== undefined) {
213+
if (attrs.disabled !== undefined) {
214+
attrsDisabled = ' ui-disable-choice="' + attrs.disabled + '"';
215+
} else {
216+
attrsDisabled = '';
217+
}
218+
}
219+
211220
return compileTemplate(
212221
'<ui-select ng-model="selection.selected"> \
213222
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
214-
<ui-select-choices repeat="person in people | filter: $select.search"> \
223+
<ui-select-choices repeat="person in people | filter: $select.search"' + attrsDisabled + '> \
215224
<div ng-bind-html="person.name | highlight: $select.search"></div> \
216225
<div ng-bind-html="person.email | highlight: $select.search"></div> \
217226
</ui-select-choices> \
218227
</ui-select>'
219228
);
220229
}
221230

222-
beforeEach(function() {
223-
scope._people = angular.copy(scope.people);
224-
scope.people = scope.people.map(function (person) {
225-
if (person.name == 'Wladimir') {
226-
person.disabled = true;
231+
function disablePerson(opts) {
232+
opts = opts || {};
233+
234+
var key = opts.key || 'people',
235+
disableAttr = opts.disableAttr || 'disabled',
236+
disableBool = opts.disableBool === undefined ? true : opts.disableBool,
237+
matchAttr = opts.match || 'name',
238+
matchVal = opts.matchVal || 'Wladimir';
239+
240+
scope['_' + key] = angular.copy(scope[key]);
241+
scope[key].map(function (model) {
242+
if (model[matchAttr] == matchVal) {
243+
model[disableAttr] = disableBool;
227244
}
228-
return person;
245+
return model;
229246
});
247+
}
248+
249+
function resetScope(opts) {
250+
opts = opts || {};
251+
var key = opts.key || 'people';
252+
scope[key] = angular.copy(scope['_' + key]);
253+
}
254+
255+
describe('without disabling expression', function () {
256+
beforeEach(function() {
257+
disablePerson();
258+
this.el = createUiSelect();
259+
});
260+
261+
it('should not allow disabled options to be selected', function() {
262+
clickItem(this.el, 'Wladimir');
230263

231-
this.el = createUiSelect();
264+
expect(getMatchLabel(this.el)).toEqual('Wladimir');
265+
});
266+
267+
it('should set a disabled class on the option', function() {
268+
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
269+
var container = option.closest('.ui-select-choices-row');
270+
271+
expect(container.hasClass('disabled')).toBeFalsy();
272+
});
232273
});
233274

234-
afterEach(function() {
235-
scope.people = angular.copy(scope._people);
275+
describe('disable on truthy property', function () {
276+
beforeEach(function() {
277+
disablePerson({
278+
disableAttr : 'inactive',
279+
disableBool : true,
280+
});
281+
this.el = createUiSelect({
282+
disabled: 'person.inactive'
283+
});
284+
});
285+
286+
it('should allow the user to define the selected option', function () {
287+
expect($(this.el).find('.ui-select-choices').attr('ui-disable-choice')).toBe('person.inactive');
288+
});
289+
290+
it('should not allow disabled options to be selected', function() {
291+
clickItem(this.el, 'Wladimir');
292+
293+
expect(getMatchLabel(this.el)).not.toEqual('Wladimir');
294+
});
295+
296+
it('should set a disabled class on the option', function() {
297+
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
298+
var container = option.closest('.ui-select-choices-row');
299+
300+
expect(container.hasClass('disabled')).toBeTruthy();
301+
});
236302
});
237303

238-
it('should not allow disabled options to be selected', function() {
239-
clickItem(this.el, 'Wladimir');
304+
describe('disable on inverse property check', function () {
305+
beforeEach(function() {
306+
disablePerson({
307+
disableAttr : 'active',
308+
disableBool : false,
309+
});
310+
this.el = createUiSelect({
311+
disabled: '!person.active'
312+
});
313+
});
314+
315+
it('should allow the user to define the selected option', function () {
316+
expect($(this.el).find('.ui-select-choices').attr('ui-disable-choice')).toBe('!person.active');
317+
});
240318

241-
expect(getMatchLabel(this.el)).not.toEqual('Wladimir');
319+
it('should not allow disabled options to be selected', function() {
320+
clickItem(this.el, 'Wladimir');
321+
322+
expect(getMatchLabel(this.el)).not.toEqual('Wladimir');
323+
});
324+
325+
it('should set a disabled class on the option', function() {
326+
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
327+
var container = option.closest('.ui-select-choices-row');
328+
329+
expect(container.hasClass('disabled')).toBeTruthy();
330+
});
242331
});
243332

244-
it('should set a disabled class on the option', function() {
245-
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
246-
var container = option.closest('.ui-select-choices-row');
333+
describe('disable on expression', function () {
334+
beforeEach(function() {
335+
disablePerson({
336+
disableAttr : 'status',
337+
disableBool : 'inactive'
338+
});
339+
this.el = createUiSelect({
340+
disabled: "person.status == 'inactive'"
341+
});
342+
});
343+
344+
it('should allow the user to define the selected option', function () {
345+
expect($(this.el).find('.ui-select-choices').attr('ui-disable-choice')).toBe("person.status == 'inactive'");
346+
});
347+
348+
it('should not allow disabled options to be selected', function() {
349+
clickItem(this.el, 'Wladimir');
350+
351+
expect(getMatchLabel(this.el)).not.toEqual('Wladimir');
352+
});
247353

248-
expect(container.hasClass('disabled')).toBeTruthy();
354+
it('should set a disabled class on the option', function() {
355+
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
356+
var container = option.closest('.ui-select-choices-row');
357+
358+
expect(container.hasClass('disabled')).toBeTruthy();
359+
});
360+
});
361+
362+
afterEach(function() {
363+
resetScope();
249364
});
250365
});
251366

0 commit comments

Comments
 (0)