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

Commit 17ceb65

Browse files
committed
feat(templates): Let user define disabling expression.
1 parent 33650f9 commit 17ceb65

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
@@ -156,6 +156,7 @@
156156
ctrl.resetSearchInput = undefined; // Initialized inside uiSelect directive link function
157157
ctrl.refreshDelay = undefined; // Initialized inside uiSelectChoices directive link function
158158
ctrl.multiple = false; // Initialized inside uiSelect directive link function
159+
ctrl.disableChoiceExpression = undefined; // Initialized inside uiSelect directive link function
159160

160161
ctrl.isEmpty = function() {
161162
return angular.isUndefined(ctrl.selected) || ctrl.selected === null || ctrl.selected === '';
@@ -304,9 +305,10 @@
304305
var isDisabled = false;
305306
var item;
306307

307-
if (itemIndex >= 0) {
308+
if (itemIndex >= 0 && !angular.isUndefined(ctrl.disableChoiceExpression)) {
308309
item = ctrl.items[itemIndex];
309-
isDisabled = item.disabled;
310+
isDisabled = !!(itemScope.$eval(ctrl.disableChoiceExpression)); // force the boolean value
311+
item._uiSelectChoiceDisabled = isDisabled; // store this for later reference
310312
}
311313

312314
return isDisabled;
@@ -315,7 +317,7 @@
315317
// When the user clicks on an item inside the dropdown
316318
ctrl.select = function(item) {
317319

318-
if (!item.disabled) {
320+
if (!item._uiSelectChoiceDisabled) {
319321
var locals = {};
320322
locals[ctrl.parserResult.itemName] = item;
321323

@@ -833,6 +835,8 @@
833835

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

838+
$select.disableChoiceExpression = attrs.uiDisableChoice;
839+
836840
if(groupByExp) {
837841
var groups = element.querySelectorAll('.ui-select-choices-group');
838842
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
@@ -267,45 +267,160 @@ describe('ui-select tests', function() {
267267
});
268268

269269
describe('disabled options', function() {
270-
function createUiSelect() {
270+
function createUiSelect(attrs) {
271+
var attrsDisabled = '';
272+
if (attrs !== undefined) {
273+
if (attrs.disabled !== undefined) {
274+
attrsDisabled = ' ui-disable-choice="' + attrs.disabled + '"';
275+
} else {
276+
attrsDisabled = '';
277+
}
278+
}
279+
271280
return compileTemplate(
272281
'<ui-select ng-model="selection.selected"> \
273282
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
274-
<ui-select-choices repeat="person in people | filter: $select.search"> \
283+
<ui-select-choices repeat="person in people | filter: $select.search"' + attrsDisabled + '> \
275284
<div ng-bind-html="person.name | highlight: $select.search"></div> \
276285
<div ng-bind-html="person.email | highlight: $select.search"></div> \
277286
</ui-select-choices> \
278287
</ui-select>'
279288
);
280289
}
281290

282-
beforeEach(function() {
283-
scope._people = angular.copy(scope.people);
284-
scope.people = scope.people.map(function (person) {
285-
if (person.name == 'Wladimir') {
286-
person.disabled = true;
291+
function disablePerson(opts) {
292+
opts = opts || {};
293+
294+
var key = opts.key || 'people',
295+
disableAttr = opts.disableAttr || 'disabled',
296+
disableBool = opts.disableBool === undefined ? true : opts.disableBool,
297+
matchAttr = opts.match || 'name',
298+
matchVal = opts.matchVal || 'Wladimir';
299+
300+
scope['_' + key] = angular.copy(scope[key]);
301+
scope[key].map(function (model) {
302+
if (model[matchAttr] == matchVal) {
303+
model[disableAttr] = disableBool;
287304
}
288-
return person;
305+
return model;
306+
});
307+
}
308+
309+
function resetScope(opts) {
310+
opts = opts || {};
311+
var key = opts.key || 'people';
312+
scope[key] = angular.copy(scope['_' + key]);
313+
}
314+
315+
describe('without disabling expression', function () {
316+
beforeEach(function() {
317+
disablePerson();
318+
this.el = createUiSelect();
289319
});
290320

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

294-
afterEach(function() {
295-
scope.people = angular.copy(scope._people);
335+
describe('disable on truthy property', function () {
336+
beforeEach(function() {
337+
disablePerson({
338+
disableAttr : 'inactive',
339+
disableBool : true,
340+
});
341+
this.el = createUiSelect({
342+
disabled: 'person.inactive'
343+
});
344+
});
345+
346+
it('should allow the user to define the selected option', function () {
347+
expect($(this.el).find('.ui-select-choices').attr('ui-disable-choice')).toBe('person.inactive');
348+
});
349+
350+
it('should not allow disabled options to be selected', function() {
351+
clickItem(this.el, 'Wladimir');
352+
353+
expect(getMatchLabel(this.el)).not.toEqual('Wladimir');
354+
});
355+
356+
it('should set a disabled class on the option', function() {
357+
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
358+
var container = option.closest('.ui-select-choices-row');
359+
360+
expect(container.hasClass('disabled')).toBeTruthy();
361+
});
296362
});
297363

298-
it('should not allow disabled options to be selected', function() {
299-
clickItem(this.el, 'Wladimir');
364+
describe('disable on inverse property check', function () {
365+
beforeEach(function() {
366+
disablePerson({
367+
disableAttr : 'active',
368+
disableBool : false,
369+
});
370+
this.el = createUiSelect({
371+
disabled: '!person.active'
372+
});
373+
});
374+
375+
it('should allow the user to define the selected option', function () {
376+
expect($(this.el).find('.ui-select-choices').attr('ui-disable-choice')).toBe('!person.active');
377+
});
378+
379+
it('should not allow disabled options to be selected', function() {
380+
clickItem(this.el, 'Wladimir');
381+
382+
expect(getMatchLabel(this.el)).not.toEqual('Wladimir');
383+
});
384+
385+
it('should set a disabled class on the option', function() {
386+
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
387+
var container = option.closest('.ui-select-choices-row');
300388

301-
expect(getMatchLabel(this.el)).not.toEqual('Wladimir');
389+
expect(container.hasClass('disabled')).toBeTruthy();
390+
});
302391
});
303392

304-
it('should set a disabled class on the option', function() {
305-
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
306-
var container = option.closest('.ui-select-choices-row');
393+
describe('disable on expression', function () {
394+
beforeEach(function() {
395+
disablePerson({
396+
disableAttr : 'status',
397+
disableBool : 'inactive'
398+
});
399+
this.el = createUiSelect({
400+
disabled: "person.status == 'inactive'"
401+
});
402+
});
403+
404+
it('should allow the user to define the selected option', function () {
405+
expect($(this.el).find('.ui-select-choices').attr('ui-disable-choice')).toBe("person.status == 'inactive'");
406+
});
407+
408+
it('should not allow disabled options to be selected', function() {
409+
clickItem(this.el, 'Wladimir');
410+
411+
expect(getMatchLabel(this.el)).not.toEqual('Wladimir');
412+
});
307413

308-
expect(container.hasClass('disabled')).toBeTruthy();
414+
it('should set a disabled class on the option', function() {
415+
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
416+
var container = option.closest('.ui-select-choices-row');
417+
418+
expect(container.hasClass('disabled')).toBeTruthy();
419+
});
420+
});
421+
422+
afterEach(function() {
423+
resetScope();
309424
});
310425
});
311426

0 commit comments

Comments
 (0)