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

Commit 1959ef5

Browse files
committed
Merge pull request #748 from angular-ui/fix-multiple-formatter
fix(multiple): formatter binding
2 parents 66bf8b5 + acd1157 commit 1959ef5

File tree

1 file changed

+58
-50
lines changed

1 file changed

+58
-50
lines changed

src/uiSelectMultipleDirective.js

+58-50
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,28 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec
55

66
controller: ['$scope','$timeout', function($scope, $timeout){
77

8-
var ctrl = this;
9-
var $select = $scope.$select;
8+
var ctrl = this,
9+
$select = $scope.$select,
10+
ngModel;
11+
12+
//Wait for link fn to inject it
13+
$scope.$evalAsync(function(){ ngModel = $scope.ngModel; });
1014

1115
ctrl.activeMatchIndex = -1;
1216

17+
ctrl.updateModel = function(){
18+
ngModel.$setViewValue(Date.now()); //Set timestamp as a unique string to force changes
19+
ctrl.refreshComponent();
20+
};
21+
22+
ctrl.refreshComponent = function(){
23+
//Remove already selected items
24+
//e.g. When user clicks on a selection, the selected array changes and
25+
//the dropdown should remove that item
26+
$select.refreshItems();
27+
$select.sizeSearchInput();
28+
};
29+
1330
// Remove item from multiple select
1431
ctrl.removeChoice = function(index){
1532

@@ -33,6 +50,8 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec
3350
});
3451
});
3552

53+
ctrl.updateModel();
54+
3655
};
3756

3857
ctrl.getPlaceholder = function(){
@@ -48,9 +67,11 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec
4867
link: function(scope, element, attrs, ctrls) {
4968

5069
var $select = ctrls[0];
51-
var ngModel = ctrls[1];
70+
var ngModel = scope.ngModel = ctrls[1];
5271
var $selectMultiple = scope.$selectMultiple;
5372

73+
//$select.selected = raw selected objects (ignoring any property binding)
74+
5475
$select.multiple = true;
5576
$select.removeSelected = true;
5677

@@ -76,63 +97,49 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec
7697
var data = $select.parserResult.source (scope, { $select : {search:''}}), //Overwrite $search
7798
locals = {},
7899
result;
79-
if (data){
80-
var resultMultiple = [];
81-
var checkFnMultiple = function(list, value){
82-
//if the list is empty add the value to the list
83-
if (!list || !list.length){
84-
resultMultiple.unshift(value);
85-
return true;
100+
if (!data) return inputValue;
101+
var resultMultiple = [];
102+
var checkFnMultiple = function(list, value){
103+
if (!list || !list.length) return;
104+
for (var p = list.length - 1; p >= 0; p--) {
105+
locals[$select.parserResult.itemName] = list[p];
106+
result = $select.parserResult.modelMapper(scope, locals);
107+
if($select.parserResult.trackByExp){
108+
var matches = /\.(.+)/.exec($select.parserResult.trackByExp);
109+
if(matches.length>0 && result[matches[1]] == value[matches[1]]){
110+
resultMultiple.unshift(list[p]);
111+
return true;
112+
}
86113
}
87-
for (var p = list.length - 1; p >= 0; p--) {
88-
locals[$select.parserResult.itemName] = list[p];
89-
result = $select.parserResult.modelMapper(scope, locals);
90-
if($select.parserResult.trackByExp){
91-
var matches = /\.(.+)/.exec($select.parserResult.trackByExp);
92-
if(matches.length>0 && result[matches[1]] == value[matches[1]]){
93-
resultMultiple.unshift(list[p]);
94-
return true;
95-
}
96-
}
97-
if (result == value){
98-
resultMultiple.unshift(list[p]);
99-
return true;
100-
}
114+
if (angular.equals(result,value)){
115+
resultMultiple.unshift(list[p]);
116+
return true;
101117
}
102-
return false;
103-
};
104-
if (!inputValue) return resultMultiple; //If ngModel was undefined
105-
for (var k = inputValue.length - 1; k >= 0; k--) {
106-
if (!checkFnMultiple($select.selected, inputValue[k])){
107-
checkFnMultiple(data, inputValue[k]);
118+
}
119+
return false;
120+
};
121+
if (!inputValue) return resultMultiple; //If ngModel was undefined
122+
for (var k = inputValue.length - 1; k >= 0; k--) {
123+
//Check model array of currently selected items
124+
if (!checkFnMultiple($select.selected, inputValue[k])){
125+
//Check model array of all items available
126+
if (!checkFnMultiple(data, inputValue[k])){
127+
//If not found on previous lists, just add it directly to resultMultiple
128+
resultMultiple.unshift(inputValue[k]);
108129
}
109130
}
110-
return resultMultiple;
111131
}
112-
return inputValue;
132+
return resultMultiple;
113133
});
114134

115-
//Watch selection
135+
//Watch for external model changes
116136
scope.$watchCollection(function(){ return ngModel.$modelValue; }, function(newValue, oldValue) {
117-
if (oldValue != newValue)
137+
if (oldValue != newValue){
118138
ngModel.$modelValue = null; //Force scope model value and ngModel value to be out of sync to re-run formatters
119-
});
120-
//TODO Should be a better way to detect first pass
121-
$select.firstPass = true; // so the form doesn't get dirty as soon as it loads
122-
scope.$watchCollection('$select.selected', function() {
123-
if (!$select.firstPass) {
124-
ngModel.$setViewValue(Date.now()); //Set timestamp as a unique string to force changes
125-
} else {
126-
$select.firstPass = false;
139+
$selectMultiple.refreshComponent();
127140
}
128-
//Remove already selected items
129-
//e.g. When user clicks on a selection, the selected array changes and
130-
//the dropdown should remove that item
131-
$select.refreshItems();
132-
//TODO Should add a test
133-
$select.sizeSearchInput();
134141
});
135-
142+
136143
ngModel.$render = function() {
137144
// Make sure that model value is array
138145
if(!angular.isArray(ngModel.$viewValue)){
@@ -144,11 +151,12 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec
144151
}
145152
}
146153
$select.selected = ngModel.$viewValue;
154+
scope.$evalAsync(); //To force $digest
147155
};
148156

149157
scope.$on('uis:select', function (event, item) {
150158
$select.selected.push(item);
151-
$select.sizeSearchInput();
159+
$selectMultiple.updateModel();
152160
});
153161

154162
scope.$on('uis:activate', function () {

0 commit comments

Comments
 (0)