@@ -6,6 +6,7 @@ function(decoratorsProvider, sfBuilderProvider, sfPathProvider) {
6
6
var simpleTransclusion = sfBuilderProvider . builders . simpleTransclusion ;
7
7
var ngModelOptions = sfBuilderProvider . builders . ngModelOptions ;
8
8
var ngModel = sfBuilderProvider . builders . ngModel ;
9
+ var sfField = sfBuilderProvider . builders . sfField ;
9
10
10
11
var array = function ( args ) {
11
12
console . log ( 'array' , args ) ;
@@ -24,7 +25,7 @@ function(decoratorsProvider, sfBuilderProvider, sfPathProvider) {
24
25
args . form . schema . items . type . indexOf ( 'array' ) === - 1 ) {
25
26
console . log ( 'setting state modelValue' , args . form ) ;
26
27
var strKey = sfPathProvider . stringify ( args . form . key ) . replace ( / " / g, '"' ) + '[$index]' ;
27
- state . modelValue = 'getModelArray() [$index]' ; //(args.state.modelName || 'model') + (strKey[0] !== '[' ? '.' : '') + strKey;
28
+ state . modelValue = 'modelArray [$index]' ; //(args.state.modelName || 'model') + (strKey[0] !== '[' ? '.' : '') + strKey;
28
29
//state.modelValue = 'model' + sfPathProvider.normalize(args.form.key) + '[$index]'; // 'modelArray[$index]';
29
30
} else {
30
31
state . modelName = 'item' ;
@@ -34,15 +35,15 @@ function(decoratorsProvider, sfBuilderProvider, sfPathProvider) {
34
35
items . appendChild ( childFrag ) ;
35
36
}
36
37
} ;
37
- var defaults = [ ngModel , ngModelOptions ] ;
38
+ var defaults = [ sfField , ngModel , ngModelOptions ] ;
38
39
decoratorsProvider . defineDecorator ( 'bootstrapDecorator' , {
39
40
textarea : { template : base + 'textarea.html' , builder : defaults } ,
40
- fieldset : { template : base + 'fieldset.html' , builder : simpleTransclusion } ,
41
- array : { template : base + 'array.html' , builder : [ ngModelOptions , ngModel , array ] } ,
41
+ fieldset : { template : base + 'fieldset.html' , builder : [ sfField , simpleTransclusion ] } ,
42
+ array : { template : base + 'array.html' , builder : [ sfField , ngModelOptions , ngModel , array ] } ,
42
43
tabarray : { template : base + 'tabarray.html' , replace : false } ,
43
44
tabs : { template : base + 'tabs.html' , replace : false } ,
44
- section : { template : base + 'section.html' , builder : simpleTransclusion } ,
45
- conditional : { template : base + 'section.html' , builder : simpleTransclusion } ,
45
+ section : { template : base + 'section.html' , builder : [ sfField , simpleTransclusion ] } ,
46
+ conditional : { template : base + 'section.html' , builder : [ sfField , simpleTransclusion ] } ,
46
47
actions : { template : base + 'actions.html' , builder : defaults } ,
47
48
select : { template : base + 'select.html' , builder : defaults } ,
48
49
checkbox : { template : base + 'checkbox.html' , builder : defaults } ,
@@ -58,27 +59,10 @@ function(decoratorsProvider, sfBuilderProvider, sfPathProvider) {
58
59
'default' : { template : base + 'default.html' , builder : defaults }
59
60
} , [ ] ) ;
60
61
61
- } ] ) . filter ( 'minLength' , function ( ) {
62
- return function ( input , min ) {
63
- input = input || [ ] ;
64
- var diff = min - input . length ;
65
- if ( diff > 0 ) {
66
- return input . concat ( new Array ( diff ) ) ;
67
- }
68
- return input ;
69
- } ;
70
- } ) . directive ( 'sfPropagateNgModel' , [ function ( ) {
71
- return {
72
- scope : false ,
73
- require : 'ngModel' ,
74
- link : function ( scope , element , attrs , ngModel ) {
75
- // We need the ngModelController on several places,
76
- // most notably for errors.
77
- // So we emit it up to the decorator directive so it can put it on scope.
78
- scope . $emit ( 'schemaFormPropagateNgModelController' , ngModel ) ;
79
- }
80
- } ;
81
- } ] ) . directive ( 'sfNewArray' , [ 'sfSelect' , 'sfPath' , function ( sel , sfPath ) {
62
+ } ] )
63
+
64
+ /* Directives here are WIP, will be moved to main repo or their own files when soldifying */
65
+ . directive ( 'sfNewArray' , [ 'sfSelect' , 'sfPath' , function ( sel , sfPath ) {
82
66
return {
83
67
scope : false ,
84
68
link : function ( scope , element , attrs ) {
@@ -88,69 +72,99 @@ function(decoratorsProvider, sfBuilderProvider, sfPathProvider) {
88
72
TODO
89
73
----
90
74
* se till att valideringsfel på arrayen syns tyligare, kanske över add knappen?
75
+ * kanske css för disable knappen på listor också.
91
76
* testa att ändra arrayen utanför, testa att byta ut arrayen helt utanför.
92
77
* om den inte validerar när ngt förändras får vi lägga till en watch
93
78
* testa en async validator och en vanlig $validator
94
79
* implementera onChange med en watchCollection
95
- * implementera
96
80
* disabla add och ta bort knapparna om limits har nåtts.
97
81
98
82
*/
99
83
84
+ scope . modelArray = scope . $eval ( attrs . sfNewArray ) ;
85
+
86
+ // We need to have a ngModel to hook into validation. It doesn't really play well with
87
+ // arrays though so we both need to trigger validation and onChange.
88
+ // So we watch the value as well. But watching an array can be tricky. We wan't to know
89
+ // when it changes so we can validate,
90
+ var watchFn = function ( ) {
91
+ //scope.modelArray = modelArray;
92
+ scope . modelArray = scope . $eval ( attrs . sfNewArray ) ;
93
+ console . warn ( 'array watch!' )
94
+ // validateField method is exported by schema-validate
95
+ if ( scope . validateField ) {
96
+ console . warn ( 'calling validate field' ) ;
97
+ scope . validateField ( ) ;
98
+ }
99
+ } ;
100
+
101
+ var onChangeFn = function ( ) {
102
+ if ( scope . form && scope . form . onChange ) {
103
+ if ( angular . isFunction ( form . onChange ) ) {
104
+ form . onChange ( ctrl . $modelValue , form ) ;
105
+ } else {
106
+ scope . evalExpr ( form . onChange , { 'modelValue' : ctrl . $modelValue , form : form } ) ;
107
+ }
108
+ }
109
+ } ;
110
+
111
+ // We need the form definition to make a decision on how we should listen.
112
+ var once = scope . $watch ( 'form' , function ( form ) {
113
+ if ( ! form ) {
114
+ return ;
115
+ }
116
+ // If we have "uniqueItems" set to true, we must deep watch for changes.
117
+ if ( scope . form && scope . form . schema && scope . form . schema . uniqueItems === true ) {
118
+ scope . $watch ( attrs . sfNewArray , watchFn , true ) ;
119
+
120
+ // We still need to trigger onChange though.
121
+ scope . $watch ( [ attrs . sfNewArray , attrs . sfNewArray + '.length' ] , onChangeFn ) ;
122
+
123
+ } else {
124
+ // Otherwise we like to check if the instance of the array has changed, or if something
125
+ // has been added/removed.
126
+ scope . $watch ( [ attrs . sfNewArray , attrs . sfNewArray + '.length' ] , function ( ) {
127
+ watchFn ( ) ;
128
+ onChangeFn ( ) ;
129
+ } ) ;
130
+ }
131
+
132
+ once ( ) ;
133
+ } ) ;
100
134
101
135
scope . appendToArray = function ( ) {
102
136
var empty ;
103
137
104
138
// Same old add empty things to the array hack :(
105
139
if ( scope . form && scope . form . schema ) {
106
-
107
140
if ( scope . form . schema . items ) {
108
141
if ( scope . form . schema . items . type === 'object' ) {
109
142
empty = { } ;
110
143
} else if ( scope . form . schema . items . type === 'array' ) {
111
144
empty = [ ] ;
112
145
}
113
146
}
114
-
115
- // FIXME: valdiate maxItems and minItems and make sure button is disables if needed.
116
147
}
117
148
118
- var model = scope . getModelArray ( ) ;
149
+ var model = scope . modelArray ;
119
150
if ( ! model ) {
120
151
// Create and set an array if needed.
121
152
var selection = sfPath . parse ( attrs . sfNewArray ) ;
122
153
model = [ ] ;
123
154
sel ( selection , scope , model ) ;
124
155
if ( scope . ngModel ) {
125
- ngModel . $setViewValue ( model ) ;
156
+ scope . ngModel . $setViewValue ( model ) ;
126
157
}
127
158
}
128
159
model . push ( empty ) ;
129
-
130
- // validateField method is exported by schema-validate
131
- if ( scope . validateField ) {
132
- scope . validateField ( ) ;
133
- }
134
160
} ;
135
161
136
162
scope . deleteFromArray = function ( index ) {
137
- var model = scope . getModelArray ( ) ;
163
+ var model = scope . modelArray ;
138
164
if ( model ) {
139
165
model . splice ( index , 1 ) ;
140
166
}
141
-
142
- // validateField method is exported by schema-validate
143
- if ( scope . validateField ) {
144
- scope . validateField ( ) ;
145
- }
146
- } ;
147
-
148
- scope . getModelArray = function ( ) {
149
- // Some simple perf testing sets $eval speeds at roughly the same as using sfSelect.
150
- var model = scope . $eval ( attrs . sfNewArray ) ;
151
- return model ;
152
167
} ;
153
-
154
168
}
155
169
} ;
156
170
} ] ) ;
0 commit comments