@@ -6,6 +6,7 @@ function(decoratorsProvider, sfBuilderProvider, sfPathProvider) {
66 var simpleTransclusion = sfBuilderProvider . builders . simpleTransclusion ;
77 var ngModelOptions = sfBuilderProvider . builders . ngModelOptions ;
88 var ngModel = sfBuilderProvider . builders . ngModel ;
9+ var sfField = sfBuilderProvider . builders . sfField ;
910
1011 var array = function ( args ) {
1112 console . log ( 'array' , args ) ;
@@ -24,7 +25,7 @@ function(decoratorsProvider, sfBuilderProvider, sfPathProvider) {
2425 args . form . schema . items . type . indexOf ( 'array' ) === - 1 ) {
2526 console . log ( 'setting state modelValue' , args . form ) ;
2627 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;
2829 //state.modelValue = 'model' + sfPathProvider.normalize(args.form.key) + '[$index]'; // 'modelArray[$index]';
2930 } else {
3031 state . modelName = 'item' ;
@@ -34,15 +35,15 @@ function(decoratorsProvider, sfBuilderProvider, sfPathProvider) {
3435 items . appendChild ( childFrag ) ;
3536 }
3637 } ;
37- var defaults = [ ngModel , ngModelOptions ] ;
38+ var defaults = [ sfField , ngModel , ngModelOptions ] ;
3839 decoratorsProvider . defineDecorator ( 'bootstrapDecorator' , {
3940 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 ] } ,
4243 tabarray : { template : base + 'tabarray.html' , replace : false } ,
4344 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 ] } ,
4647 actions : { template : base + 'actions.html' , builder : defaults } ,
4748 select : { template : base + 'select.html' , builder : defaults } ,
4849 checkbox : { template : base + 'checkbox.html' , builder : defaults } ,
@@ -58,27 +59,10 @@ function(decoratorsProvider, sfBuilderProvider, sfPathProvider) {
5859 'default' : { template : base + 'default.html' , builder : defaults }
5960 } , [ ] ) ;
6061
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 ) {
8266 return {
8367 scope : false ,
8468 link : function ( scope , element , attrs ) {
@@ -88,69 +72,99 @@ function(decoratorsProvider, sfBuilderProvider, sfPathProvider) {
8872TODO
8973----
9074* se till att valideringsfel på arrayen syns tyligare, kanske över add knappen?
75+ * kanske css för disable knappen på listor också.
9176* testa att ändra arrayen utanför, testa att byta ut arrayen helt utanför.
9277 * om den inte validerar när ngt förändras får vi lägga till en watch
9378* testa en async validator och en vanlig $validator
9479* implementera onChange med en watchCollection
95- * implementera
9680* disabla add och ta bort knapparna om limits har nåtts.
9781
9882*/
9983
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+ } ) ;
100134
101135 scope . appendToArray = function ( ) {
102136 var empty ;
103137
104138 // Same old add empty things to the array hack :(
105139 if ( scope . form && scope . form . schema ) {
106-
107140 if ( scope . form . schema . items ) {
108141 if ( scope . form . schema . items . type === 'object' ) {
109142 empty = { } ;
110143 } else if ( scope . form . schema . items . type === 'array' ) {
111144 empty = [ ] ;
112145 }
113146 }
114-
115- // FIXME: valdiate maxItems and minItems and make sure button is disables if needed.
116147 }
117148
118- var model = scope . getModelArray ( ) ;
149+ var model = scope . modelArray ;
119150 if ( ! model ) {
120151 // Create and set an array if needed.
121152 var selection = sfPath . parse ( attrs . sfNewArray ) ;
122153 model = [ ] ;
123154 sel ( selection , scope , model ) ;
124155 if ( scope . ngModel ) {
125- ngModel . $setViewValue ( model ) ;
156+ scope . ngModel . $setViewValue ( model ) ;
126157 }
127158 }
128159 model . push ( empty ) ;
129-
130- // validateField method is exported by schema-validate
131- if ( scope . validateField ) {
132- scope . validateField ( ) ;
133- }
134160 } ;
135161
136162 scope . deleteFromArray = function ( index ) {
137- var model = scope . getModelArray ( ) ;
163+ var model = scope . modelArray ;
138164 if ( model ) {
139165 model . splice ( index , 1 ) ;
140166 }
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 ;
152167 } ;
153-
154168 }
155169 } ;
156170} ] ) ;
0 commit comments