@@ -149,63 +149,53 @@ djng_forms_module.directive('ngModel', function() {
149149} ) ;
150150
151151
152+ // This directive is added automatically by django-angular for widgets of type RadioSelect and
153+ // CheckboxSelectMultiple. This is necessary to adjust the behavior of a collection of input fields,
154+ // which forms a group for one `django.forms.Field`.
152155djng_forms_module . directive ( 'validateMultipleFields' , function ( ) {
153156 return {
154157 restrict : 'A' ,
155158 require : '^?form' ,
156- // create child scope for changed method
157- scope : true ,
158- compile : function ( element , attrs ) {
159- angular . forEach ( element . find ( 'input' ) , function ( elem ) {
160- elem = angular . element ( elem )
161- elem . attr ( 'ng-change' , 'changed()' ) ;
162- } ) ;
163-
164- return {
165-
166- post : function ( scope , element , attrs , controller ) {
167- var formCtrl , subFields , checkboxCtrls = [ ] ;
168-
169- scope . changed = function ( ) {
170- validate ( true )
171- }
172-
173- function validate ( trigger ) {
174- var valid = false ;
175- angular . forEach ( checkboxCtrls , function ( checkbox ) {
176- valid = valid || checkbox . $modelValue ;
177- if ( checkbox . clearRejected ) {
178- checkbox . clearRejected ( ) ;
179- }
180- } ) ;
181-
182- formCtrl . $setValidity ( 'required' , valid ) ;
183- formCtrl . $setValidity ( 'rejected' , true ) ;
184- formCtrl . $message = ''
185-
186- if ( trigger && angular . isString ( subFields ) ) {
187- formCtrl [ subFields ] . $dirty = true ;
188- formCtrl [ subFields ] . $pristine = false ;
189- }
190- }
191-
192- if ( ! controller )
193- return ;
194- formCtrl = controller ;
195- try {
196- subFields = angular . fromJson ( attrs . validateMultipleFields ) ;
197- } catch ( SyntaxError ) {
198- subFields = attrs . validateMultipleFields ;
199- }
200- angular . forEach ( element . find ( 'input' ) , function ( elem ) {
201- if ( subFields . indexOf ( elem . name ) >= 0 ) {
202- checkboxCtrls . push ( formCtrl [ elem . name ] ) ;
203- }
204- } ) ;
159+ link : function ( scope , element , attrs , formCtrl ) {
160+ var subFields , checkboxElems = [ ] ;
205161
206- validate ( ) ;
162+ function validate ( event ) {
163+ var valid = false ;
164+ angular . forEach ( checkboxElems , function ( checkbox ) {
165+ valid = valid || checkbox . checked ;
166+ } ) ;
167+ formCtrl . $setValidity ( 'required' , valid ) ;
168+ if ( event ) {
169+ formCtrl . $dirty = true ;
170+ formCtrl . $pristine = false ;
171+ scope . $apply ( ) ;
207172 }
208173 }
174+
175+ if ( ! formCtrl )
176+ return ;
177+ try {
178+ subFields = angular . fromJson ( attrs . validateMultipleFields ) ;
179+ } catch ( SyntaxError ) {
180+ if ( ! angular . isString ( attrs . validateMultipleFields ) )
181+ return ;
182+ subFields = [ attrs . validateMultipleFields ] ;
183+ formCtrl = formCtrl [ subFields ] ;
184+ }
185+ angular . forEach ( element . find ( 'input' ) , function ( elem ) {
186+ if ( subFields . indexOf ( elem . name ) >= 0 ) {
187+ checkboxElems . push ( elem ) ;
188+ angular . element ( elem ) . on ( 'change' , validate ) ;
189+ }
190+ } ) ;
191+
192+ // remove "change" event handlers from each input field
193+ element . on ( '$destroy' , function ( ) {
194+ angular . forEach ( element . find ( 'input' ) , function ( elem ) {
195+ angular . element ( elem ) . off ( 'change' ) ;
196+ } ) ;
197+ } ) ;
198+ validate ( ) ;
209199 }
210200 } ;
211201} ) ;
@@ -290,7 +280,7 @@ djng_forms_module.factory('djangoForm', function() {
290280
291281 return {
292282 // setErrors takes care of updating prepared placeholder fields for displaying form errors
293- // deteced by an AJAX submission. Returns true if errors have been added to the form.
283+ // detected by an AJAX submission. Returns true if errors have been added to the form.
294284 setErrors : function ( form , errors ) {
295285 // remove errors from this form, which may have been rejected by an earlier validation
296286 form . $message = '' ;
@@ -351,4 +341,27 @@ djng_forms_module.factory('djangoForm', function() {
351341} ) ;
352342
353343
344+ // This directive behaves similar to `ng-bind` but leaves the elements content as is, if the
345+ // value to bind is undefined. This allows to set a default value in case the scope variables
346+ // are not ready yet.
347+ djng_forms_module . directive ( 'djngBindIf' , function ( ) {
348+ return {
349+ restrict : 'A' ,
350+ compile : function ( templateElement ) {
351+ templateElement . addClass ( 'ng-binding' ) ;
352+ return function ( scope , element , attr ) {
353+ element . data ( '$binding' , attr . ngBind ) ;
354+ scope . $watch ( attr . djngBindIf , function ngBindWatchAction ( value ) {
355+ // We are purposefully using == here rather than === because we want to
356+ // catch when value is "null or undefined"
357+ // jshint -W041
358+ if ( value == undefined )
359+ return ;
360+ element . text ( value ) ;
361+ } ) ;
362+ } ;
363+ }
364+ } ;
365+ } ) ;
366+
354367} ) ( window . angular ) ;
0 commit comments