@@ -5,11 +5,28 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec
5
5
6
6
controller : [ '$scope' , '$timeout' , function ( $scope , $timeout ) {
7
7
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 ; } ) ;
10
14
11
15
ctrl . activeMatchIndex = - 1 ;
12
16
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
+
13
30
// Remove item from multiple select
14
31
ctrl . removeChoice = function ( index ) {
15
32
@@ -33,6 +50,8 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec
33
50
} ) ;
34
51
} ) ;
35
52
53
+ ctrl . updateModel ( ) ;
54
+
36
55
} ;
37
56
38
57
ctrl . getPlaceholder = function ( ) {
@@ -48,9 +67,11 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec
48
67
link : function ( scope , element , attrs , ctrls ) {
49
68
50
69
var $select = ctrls [ 0 ] ;
51
- var ngModel = ctrls [ 1 ] ;
70
+ var ngModel = scope . ngModel = ctrls [ 1 ] ;
52
71
var $selectMultiple = scope . $selectMultiple ;
53
72
73
+ //$select.selected = raw selected objects (ignoring any property binding)
74
+
54
75
$select . multiple = true ;
55
76
$select . removeSelected = true ;
56
77
@@ -76,63 +97,49 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec
76
97
var data = $select . parserResult . source ( scope , { $select : { search :'' } } ) , //Overwrite $search
77
98
locals = { } ,
78
99
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
+ }
86
113
}
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 ;
101
117
}
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 ] ) ;
108
129
}
109
130
}
110
- return resultMultiple ;
111
131
}
112
- return inputValue ;
132
+ return resultMultiple ;
113
133
} ) ;
114
134
115
- //Watch selection
135
+ //Watch for external model changes
116
136
scope . $watchCollection ( function ( ) { return ngModel . $modelValue ; } , function ( newValue , oldValue ) {
117
- if ( oldValue != newValue )
137
+ if ( oldValue != newValue ) {
118
138
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 ( ) ;
127
140
}
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 ( ) ;
134
141
} ) ;
135
-
142
+
136
143
ngModel . $render = function ( ) {
137
144
// Make sure that model value is array
138
145
if ( ! angular . isArray ( ngModel . $viewValue ) ) {
@@ -144,11 +151,12 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec
144
151
}
145
152
}
146
153
$select . selected = ngModel . $viewValue ;
154
+ scope . $evalAsync ( ) ; //To force $digest
147
155
} ;
148
156
149
157
scope . $on ( 'uis:select' , function ( event , item ) {
150
158
$select . selected . push ( item ) ;
151
- $select . sizeSearchInput ( ) ;
159
+ $selectMultiple . updateModel ( ) ;
152
160
} ) ;
153
161
154
162
scope . $on ( 'uis:activate' , function ( ) {
0 commit comments