@@ -266,6 +266,164 @@ describe('ui-select tests', function() {
266266 expect ( getMatchLabel ( el ) ) . toEqual ( 'false' ) ;
267267 } ) ;
268268
269+ describe ( 'disabled options' , function ( ) {
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+
280+ return compileTemplate (
281+ '<ui-select ng-model="selection.selected"> \
282+ <ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
283+ <ui-select-choices repeat="person in people | filter: $select.search"' + attrsDisabled + '> \
284+ <div ng-bind-html="person.name | highlight: $select.search"></div> \
285+ <div ng-bind-html="person.email | highlight: $select.search"></div> \
286+ </ui-select-choices> \
287+ </ui-select>'
288+ ) ;
289+ }
290+
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 ;
304+ }
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 ( ) ;
319+ } ) ;
320+
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+ } ) ;
333+ } ) ;
334+
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+ } ) ;
362+ } ) ;
363+
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' ) ;
388+
389+ expect ( container . hasClass ( 'disabled' ) ) . toBeTruthy ( ) ;
390+ } ) ;
391+ } ) ;
392+
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+ } ) ;
413+
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 ( ) ;
424+ } ) ;
425+ } ) ;
426+
269427 describe ( 'choices group' , function ( ) {
270428 function getGroupLabel ( item ) {
271429 return item . parent ( '.ui-select-choices-group' ) . find ( '.ui-select-choices-group-label' ) ;
0 commit comments