Skip to content

Commit a5e98dc

Browse files
committed
feat(events): expose on-open and on-close callbacks
Closes angular-ui#432 angular-ui#1153
1 parent d1994fb commit a5e98dc

File tree

3 files changed

+117
-8
lines changed

3 files changed

+117
-8
lines changed

src/uiSelectController.js

+26-6
Original file line numberDiff line numberDiff line change
@@ -340,15 +340,15 @@ uis.controller('uiSelectCtrl',
340340
function _isItemDisabled(item) {
341341
return disabledItems.indexOf(item) > -1;
342342
}
343-
343+
344344
ctrl.isDisabled = function(itemScope) {
345345

346346
if (!ctrl.open) return;
347347

348348
var item = itemScope[ctrl.itemProperty];
349349
var itemIndex = ctrl.items.indexOf(item);
350350
var isDisabled = false;
351-
351+
352352
if (itemIndex >= 0 && (angular.isDefined(ctrl.disableChoiceExpression) || ctrl.multiple)) {
353353

354354
if (item.isTag) return false;
@@ -360,7 +360,7 @@ uis.controller('uiSelectCtrl',
360360
if (!isDisabled && angular.isDefined(ctrl.disableChoiceExpression)) {
361361
isDisabled = !!(itemScope.$eval(ctrl.disableChoiceExpression));
362362
}
363-
363+
364364
_updateItemDisabled(item, isDisabled);
365365
}
366366

@@ -472,7 +472,27 @@ uis.controller('uiSelectCtrl',
472472
}
473473
};
474474

475-
// Set default function for locked choices - avoids unnecessary
475+
$scope.$watch(function(){
476+
return ctrl.open;
477+
}, function(openState, previousState){
478+
if (openState !== previousState) {
479+
var locals = {};
480+
locals[ctrl.parserResult.itemName] = ctrl.selected;
481+
if (openState && ctrl.onOpenCallback){
482+
ctrl.onOpenCallback($scope, {
483+
$item: ctrl.selected,
484+
$model: ctrl.parserResult.modelMapper($scope, locals)
485+
});
486+
} else if (!openState && ctrl.onCloseCallback){
487+
ctrl.onCloseCallback($scope, {
488+
$item: ctrl.selected,
489+
$model: ctrl.parserResult.modelMapper($scope, locals)
490+
});
491+
}
492+
}
493+
});
494+
495+
// Set default function for locked choices - avoids unnecessary
476496
// logic if functionality is not being used
477497
ctrl.isLocked = function () {
478498
return false;
@@ -484,7 +504,7 @@ uis.controller('uiSelectCtrl',
484504

485505
function _initaliseLockedChoices(doInitalise) {
486506
if(!doInitalise) return;
487-
507+
488508
var lockedItems = [];
489509

490510
function _updateItemLocked(item, isLocked) {
@@ -518,7 +538,7 @@ uis.controller('uiSelectCtrl',
518538
return isLocked;
519539
};
520540
}
521-
541+
522542

523543
var sizeWatch = null;
524544
var updaterScheduled = false;

src/uiSelectDirective.js

+2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ uis.directive('uiSelect',
5959

6060
$select.onSelectCallback = $parse(attrs.onSelect);
6161
$select.onRemoveCallback = $parse(attrs.onRemove);
62+
$select.onOpenCallback = $parse(attrs.onOpen);
63+
$select.onCloseCallback = $parse(attrs.onClose);
6264

6365
//Set reference to ngModel from uiSelectCtrl
6466
$select.ngModel = ngModel;

test/select.spec.js

+89-2
Original file line numberDiff line numberDiff line change
@@ -1375,6 +1375,93 @@ describe('ui-select tests', function() {
13751375
expect(scope.$model).toBe(scope.$item);
13761376
});
13771377

1378+
it('should invoke open callback on open', function () {
1379+
1380+
scope.onOpenFn = function(){};
1381+
spyOn(scope, 'onOpenFn');
1382+
1383+
var el = compileTemplate(
1384+
'<ui-select on-open="onOpenFn($item, $model)" ng-model="selection.selected"> \
1385+
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
1386+
<ui-select-choices repeat="person.name as person in people | filter: $select.search"> \
1387+
<div ng-bind-html="person.name | highlight: $select.search"></div> \
1388+
<div ng-bind-html="person.email | highlight: $select.search"></div> \
1389+
</ui-select-choices> \
1390+
</ui-select>'
1391+
);
1392+
1393+
openDropdown(el);
1394+
1395+
expect(scope.onOpenFn).toHaveBeenCalled();
1396+
expect(scope.onOpenFn.calls.count()).not.toBe(2);
1397+
1398+
});
1399+
1400+
it('should pass params to the open callback', function () {
1401+
1402+
scope.onOpenFn = function(){};
1403+
spyOn(scope, 'onOpenFn');
1404+
1405+
var el = compileTemplate(
1406+
'<ui-select on-open="onOpenFn($item, $model)" ng-model="selection.selected"> \
1407+
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
1408+
<ui-select-choices repeat="person.name as person in people | filter: $select.search"> \
1409+
<div ng-bind-html="person.name | highlight: $select.search"></div> \
1410+
<div ng-bind-html="person.email | highlight: $select.search"></div> \
1411+
</ui-select-choices> \
1412+
</ui-select>'
1413+
);
1414+
1415+
clickItem(el, 'Samantha');
1416+
1417+
expect(scope.onOpenFn).toHaveBeenCalledWith(undefined, undefined);
1418+
1419+
});
1420+
1421+
it('should invoke close callback on close', function () {
1422+
1423+
scope.onCloseFn = function(){};
1424+
spyOn(scope, 'onCloseFn');
1425+
1426+
var el = compileTemplate(
1427+
'<ui-select on-close="onCloseFn($item, $model)" ng-model="selection.selected"> \
1428+
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
1429+
<ui-select-choices repeat="person.name as person in people | filter: $select.search"> \
1430+
<div ng-bind-html="person.name | highlight: $select.search"></div> \
1431+
<div ng-bind-html="person.email | highlight: $select.search"></div> \
1432+
</ui-select-choices> \
1433+
</ui-select>'
1434+
);
1435+
1436+
openDropdown(el);
1437+
closeDropdown(el);
1438+
1439+
expect(scope.onCloseFn).toHaveBeenCalled();
1440+
expect(scope.onCloseFn.calls.count()).not.toBe(2);
1441+
1442+
});
1443+
1444+
it('should pass params to the close callback', function () {
1445+
1446+
scope.onCloseFn = function(){};
1447+
spyOn(scope, 'onCloseFn');
1448+
1449+
var el = compileTemplate(
1450+
'<ui-select on-close="onCloseFn($item, $model)" ng-model="selection.selected"> \
1451+
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
1452+
<ui-select-choices repeat="person.name as person in people | filter: $select.search"> \
1453+
<div ng-bind-html="person.name | highlight: $select.search"></div> \
1454+
<div ng-bind-html="person.email | highlight: $select.search"></div> \
1455+
</ui-select-choices> \
1456+
</ui-select>'
1457+
);
1458+
1459+
clickItem(el, 'Samantha');
1460+
1461+
expect(scope.onCloseFn).toHaveBeenCalledWith(scope.people[5], 'Samantha');
1462+
1463+
});
1464+
13781465
it('should allow creating tag in single select mode with tagging enabled', function() {
13791466

13801467
scope.taggingFunc = function (name) {
@@ -2527,7 +2614,7 @@ describe('ui-select tests', function() {
25272614
expect(el.scope().$select.items[1]).toEqual(jasmine.objectContaining({name: 'Amalie', email: '[email protected]'}));
25282615
});
25292616

2530-
2617+
25312618
it('should have tolerance for undefined values', function () {
25322619

25332620
scope.modelValue = undefined;
@@ -2563,7 +2650,7 @@ describe('ui-select tests', function() {
25632650

25642651
expect($(el).scope().$select.selected).toEqual([]);
25652652
});
2566-
2653+
25672654
it('should allow paste tag from clipboard', function() {
25682655
scope.taggingFunc = function (name) {
25692656
return {

0 commit comments

Comments
 (0)