@@ -267,6 +267,42 @@ var inputType = {
267
267
*/
268
268
'email' : emailInputType ,
269
269
270
+ /**
271
+ * @ngdoc inputType
272
+ * @name angular.module.ng.$compileProvider.directive.input.file
273
+ *
274
+ * @description
275
+ * HTML file input field.
276
+ *
277
+ * @param {string } ngModel Assignable angular expression to data-bind to.
278
+ * @param {string } multiple Allows multiple files selection.
279
+ * @param {string= } name Property name of the form under which the control is published.
280
+ *
281
+ * @example
282
+ <doc:example>
283
+ <doc:source>
284
+ <script>
285
+ function Ctrl($scope) {
286
+ }
287
+ </script>
288
+ <form name="myForm" ng-controller="Ctrl">
289
+ file: <input type="file" ng-model="file"> single file selection.<br/>
290
+ files: <input type="file" ng-model="files" multiple> multi-file selection.<br/>
291
+ <tt>file.name = {{file.name}}</tt><br/>
292
+ <tt>files.length = {{files.length}}</tt><br/>
293
+ </form>
294
+ </doc:source>
295
+ <doc:scenario>
296
+ it('should change state', function() {
297
+ expect(binding('file.name')).toBeUndefined();
298
+
299
+ input('file').select('a file name');
300
+ expect(binding('file.name')).toEqual('a file name');
301
+ });
302
+ </doc:scenario>
303
+ </doc:example>
304
+ */
305
+ 'file' : fileInputType ,
270
306
271
307
/**
272
308
* @ngdoc inputType
@@ -575,6 +611,33 @@ function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
575
611
ctrl . $parsers . push ( emailValidator ) ;
576
612
}
577
613
614
+ function fileInputType ( scope , element , attr , ctrl ) {
615
+ element . bind ( 'change' , function ( ) {
616
+ scope . $apply ( function ( ) {
617
+ var files = element [ 0 ] . files ,
618
+ isValid = true ;
619
+
620
+ if ( attr . accept ) {
621
+ var i , j , acceptType , fileType ,
622
+ types = map ( attr . accept . split ( ',' ) , function ( t ) { return trim ( t ) . split ( '/' ) ; } ) ;
623
+ for ( i = 0 ; i < files . length && isValid ; ++ i ) {
624
+ fileType = files [ i ] . type . split ( '/' ) ;
625
+ isValid = false ;
626
+ for ( j = 0 ; j < types . length && ! isValid ; ++ j ) {
627
+ acceptType = types [ j ] ;
628
+ isValid = acceptType [ 0 ] === fileType [ 0 ] && ( acceptType [ 1 ] === '*' || acceptType [ 1 ] === fileType [ 1 ] ) ;
629
+ }
630
+ }
631
+ }
632
+ ctrl . $setValidity ( 'file' , isValid ) ;
633
+
634
+ var viewValue ;
635
+ if ( isValid ) viewValue = attr . multiple ? files : files [ 0 ] ;
636
+ ctrl . $setViewValue ( viewValue ) ;
637
+ } ) ;
638
+ } ) ;
639
+ }
640
+
578
641
function radioInputType ( scope , element , attr , ctrl ) {
579
642
// make the name unique, if not defined
580
643
if ( isUndefined ( attr . name ) ) {
@@ -896,7 +959,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', 'ngModel', '$e
896
959
} catch ( e ) {
897
960
$exceptionHandler ( e ) ;
898
961
}
899
- } )
962
+ } ) ;
900
963
}
901
964
} ;
902
965
0 commit comments