├── .gitignore ├── LICENSE ├── README.md ├── bower.json ├── build.sh ├── demo ├── index.html └── js │ └── app.js ├── dist ├── angular-bootstrap-file-field.min.js └── angular-bootstrap-file-field.min.js.map └── src └── angular-bootstrap-file-field.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Lenny 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Angular Bootstrap File Field 2 | ======================== 3 | 4 | A pure angular (no jquery) file field that functions like the native file input field but is displayed as a bootstrap button (also works without bootstrap see "styling" below) instead of the ugly system file upload field. 5 | 6 | Adds support for `ng-model` and image preview. 7 | 8 | Actions speak louder than words: [Check out THE DEMO](http://itslenny.github.io/angular-bootstrap-file-field/). 9 | 10 | ##Installation 11 | 12 | Dependencies: Angular 13 | 14 | Download and include angular-bootstrap-file-field.min.js 15 | 16 | Create an angular app and inject `bootstrap.fileField`. That's about it. 17 | 18 | **bower** 19 | ```bash 20 | bower install angular-bootstrap-file-field 21 | ``` 22 | 23 | ##Usage 24 | 25 | **Minimal** 26 | 27 | ```html 28 | Add File 29 | ``` 30 | 31 | **Show file name** 32 | 33 | ```html 34 | Add File 35 | 36 | {{uploadFile.name}} 37 | ``` 38 | 39 | **Show image preview** 40 | 41 | ```html 42 | Select File 43 | 44 | 45 | ``` 46 | 47 | 48 | ##Configuration 49 | 50 | **Options** 51 | 52 | | Name | Values | Description | 53 | |---|---|---| 54 | | ng-model | scope variable | Behaves like ng-model on any other form element. Just binds to the $scope value in the controller. | 55 | | preview | scope variable | Optional. If provided a base64 encoded image url will be provided. (this can be used in the ng-src or an img tag to display a preview | 56 | 57 | 58 | ##Styling 59 | 60 | This directive creates a ` 38 | 39 | 40 |
41 |

Preview

42 | 43 |
44 | {{uploadFile.name}} 45 |
46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /demo/js/app.js: -------------------------------------------------------------------------------- 1 | angular.module('uploadTest',['bootstrap.fileField']) 2 | .controller('uploadTestCtrl',['$scope',function($scope){ 3 | 4 | $scope.doUpload = function(){ 5 | 6 | console.log('title',$scope.title); 7 | console.log('uploadFile',$scope.uploadFile); 8 | alert('Do upload. See console for data'); 9 | 10 | 11 | /* 12 | 13 | //create form data object 14 | var fd = new FormData(); 15 | fd.append('title',$scope.title); 16 | fd.append('file', $scope.uploadFile); 17 | 18 | //send the file / data to your server 19 | $http.post('/file/upload/path', fd, { 20 | transformRequest: angular.identity, 21 | headers: {'Content-Type': undefined} 22 | }).success(function(data){ 23 | //do something on success 24 | }).error(function(err){ 25 | //do something on error 26 | }) 27 | */ 28 | } 29 | 30 | }]); -------------------------------------------------------------------------------- /dist/angular-bootstrap-file-field.min.js: -------------------------------------------------------------------------------- 1 | /* @preserve 2 | * 3 | * angular-bootstrap-file 4 | * https://github.com/itslenny/angular-bootstrap-file-field 5 | * 6 | * Version: 0.1.3 - 02/21/2015 7 | * License: MIT 8 | */ 9 | angular.module("bootstrap.fileField",[]).directive("fileField",function(){return{require:"ngModel",restrict:"E",link:function(scope,element,attrs,ngModel){if(!attrs.class&&!attrs.ngClass){element.addClass("btn")}var fileField=element.find("input");if(attrs.accept){fileField.attr("accept",attrs.accept)}fileField.bind("change",function(event){scope.$evalAsync(function(){ngModel.$setViewValue(event.target.files[0]);if(attrs.preview){var reader=new FileReader;reader.onload=function(e){scope.$evalAsync(function(){scope[attrs.preview]=e.target.result})};reader.readAsDataURL(event.target.files[0])}})});fileField.bind("click",function(e){e.stopPropagation()});element.bind("click",function(e){e.preventDefault();fileField[0].click()})},template:'',replace:true,transclude:true}}); 10 | //# sourceMappingURL=angular-bootstrap-file-field.min.js.map -------------------------------------------------------------------------------- /dist/angular-bootstrap-file-field.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["./src/angular-bootstrap-file-field.js"],"names":["angular","module","directive","require","restrict","link","scope","element","attrs","ngModel","class","ngClass","addClass","fileField","find","accept","attr","bind","event","$evalAsync","$setViewValue","target","files","preview","reader","FileReader","onload","e","result","readAsDataURL","stopPropagation","preventDefault","click","template","replace","transclude"],"mappings":";;;;;;;;AASAA,QAAQC,OAAO,0BACdC,UAAU,YAAa,WACtB,OACEC,QAAQ,UACRC,SAAU,IACVC,KAAM,SAAUC,MAAOC,QAASC,MAAOC,SAEnC,IAAID,MAAME,QAAUF,MAAMG,QAAQ,CAC9BJ,QAAQK,SAAS,OAGrB,GAAIC,WAAYN,QAAQO,KAAK,QAG7B,IAAIN,MAAMO,OAAQ,CAChBF,UAAUG,KAAK,SAAUR,MAAMO,QAGjCF,UAAUI,KAAK,SAAU,SAASC,OAC9BZ,MAAMa,WAAW,WACfV,QAAQW,cAAcF,MAAMG,OAAOC,MAAM,GACzC,IAAGd,MAAMe,QAAQ,CACf,GAAIC,QAAS,GAAIC,WACjBD,QAAOE,OAAS,SAAUC,GACtBrB,MAAMa,WAAW,WACbb,MAAME,MAAMe,SAASI,EAAEN,OAAOO,SAGtCJ,QAAOK,cAAcX,MAAMG,OAAOC,MAAM,QAIhDT,WAAUI,KAAK,QAAQ,SAASU,GAC5BA,EAAEG,mBAENvB,SAAQU,KAAK,QAAQ,SAASU,GAC1BA,EAAEI,gBACFlB,WAAU,GAAGmB,WAGrBC,SAAS,yGACTC,QAAQ,KACRC,WAAW","file":"./dist/angular-bootstrap-file-field.min.js"} -------------------------------------------------------------------------------- /src/angular-bootstrap-file-field.js: -------------------------------------------------------------------------------- 1 | /* @preserve 2 | * 3 | * angular-bootstrap-file 4 | * https://github.com/itslenny/angular-bootstrap-file-field 5 | * 6 | * Version: 0.1.3 - 02/21/2015 7 | * License: MIT 8 | */ 9 | 10 | angular.module('bootstrap.fileField',[]) 11 | .directive('fileField', function() { 12 | return { 13 | require:'ngModel', 14 | restrict: 'E', 15 | link: function (scope, element, attrs, ngModel) { 16 | //set default bootstrap class 17 | if(!attrs.class && !attrs.ngClass){ 18 | element.addClass('btn'); 19 | } 20 | 21 | var fileField = element.find('input'); 22 | 23 | //If an ACCEPT attribute was provided, add it to the input. 24 | if (attrs.accept) { 25 | fileField.attr('accept', attrs.accept); 26 | } 27 | 28 | fileField.bind('change', function(event){ 29 | scope.$evalAsync(function () { 30 | ngModel.$setViewValue(event.target.files[0]); 31 | if(attrs.preview){ 32 | var reader = new FileReader(); 33 | reader.onload = function (e) { 34 | scope.$evalAsync(function(){ 35 | scope[attrs.preview]=e.target.result; 36 | }); 37 | }; 38 | reader.readAsDataURL(event.target.files[0]); 39 | } 40 | }); 41 | }); 42 | fileField.bind('click',function(e){ 43 | e.stopPropagation(); 44 | }); 45 | element.bind('click',function(e){ 46 | e.preventDefault(); 47 | fileField[0].click(); 48 | }); 49 | }, 50 | template:'', 51 | replace:true, 52 | transclude:true 53 | }; 54 | }); 55 | --------------------------------------------------------------------------------