Giter Club home page Giter Club logo

ngupload's Introduction

ngUpload

An AngularJS file upload directive. Demo http://ngupload.herokuapp.com

0.5.18 - for updates see CHANGELOG.md

   <form ng-upload="uploadComplete(content)" action="/upload-full-form">
       <p>
           <label>Fullname:</label>
           <input type="text" name="fullname" ng-model="fullname" />
       </p>
       <p>
           <label>Gender:</label>
           <input type="text" name="gender" ng-model="gender" />
       </p>
       <p>
           <label>Favorite Color:</label>
           <input type="text" name="color" ng-model="color"/>
       </p>
       <p>
           <label>Your picture (file will not be saved on the server):</label>
           <input type="file" name="file" />
       </p>
       <p>
           <input type="submit" class="btn" value="Submit" ng-disabled="$isUploading"  />
       </p>
   </form>
   <div class="alert alert-info">Server Response: {{response | json}}</div>
   <div>
       Fullname: <b>{{response.fullname}}</b><br />
       Gender: <b>{{response.gender}}</b><br />
       Favourite Color: <span ng-style="response.style">{{response.color}}</span><br />
       Picture: {{response.pictureUrl}}
   </div>

... and the context ngController's source is:

app.controller('Example5Ctrl', function ($scope) {
  $scope.uploadComplete = function (content) {
    $scope.response = JSON.parse(content); // Presumed content is a json string!
    $scope.response.style = {
      color: $scope.response.color,
      "font-weight": "bold"
    };

    // Clear form (reason for using the 'ng-model' directive on the input elements)
    $scope.fullname = '';
    $scope.gender = '';
    $scope.color = '';
    // Look for way to clear the input[type=file] element
  };
});

Requirements

Install with NPM

npm install ngUpload -S

Install with Bower

bower install ngUpload

Usage

Add to your html file

<script src="/js/ng-upload.js"></script>

Create a basic form with a file input element

<div ng-app="app">
  <div ng-controller="mainCtrl">
   <form action="/uploads" ng-upload="complete(content)">
     <input type="file" name="avatar"></input>
     <input type="submit" value="Upload" ng-disabled="$isUploading"></input>
   </form>
 </div>
</div>

Some rule of thumb

  • Any html element that supports the click event can be used to submit the form marked with the ng-upload directive, as long as such elements are marked with the 'upload-submit' directive. If you use an input element with a type of submit then you do not have to mark it with upload-submit.
  • Make sure you import the 'ngUpload' module in your angularJS application.

Applying this rules, the sample above can be re-written as

<div ng-app="app">
  <div ng-controller="mainCtrl">
   <form action="/uploads" ng-upload="complete(content)">
     <input type="file" name="avatar"></input>
     <div style='cursor: pointer' upload-submit>Upload with Div</div> &bull;
   </form>
 </div>
</div>

or

<div ng-app="app">
  <div ng-controller="mainCtrl">
   <form action="/uploads" ng-upload="complete(contents)">
     <input type="file" name="avatar"></input>
     <a href='javascript:void(0)'
       class="upload-submit" >
         Upload with Anchor</a>
   </form>
 </div>
</div>

where the form can be submit with a Div or Anchor html element.

The AngularJS controller for the above samples is given as:

angular.module('app', ['ngUpload'])
  .controller('mainCtrl', function($scope) {
    $scope.complete = function(content) {
      console.log(content); // process content
    }
});
  • Working in IE

In order, for ngUpload to respond correctly for IE, your server needs to return the response back as text/html not application/json

Directive Options

ngUpload

  • upload-options-enable-rails-csrf: Turns on support for Rails' CSRF by adding a hidden form field with the csrf token.

  • upload-options-before-submit: function that gets triggered before the upload starts and if the function returns false it will cancel the submit.

uploadSubmit

  • upload-options-convert-hidden: Set the value of hidden inputs to their ng-model attribute when the form is submitted. One situation in which this is useful is when using select elements whose options are generated with ngOptions, for example:
select[name='category_id' ng-model='category' ng-options='c.id as c.name for c in categories']

and where categories is

[{id: 12, name: 'fred'}, {id: 65, name: 'wilma'}]

Because Angular will generate options whose HTML element value is indexed on 0, the value submitted will be the value of the option and not the desired ng-model value which is category.id. Adding a hidden element whose ng-model matches the ng-model of the select element, combined with upload-options-convert-hidden='true' will workaround this issue.

Example

Example of forms that posts to NodeJS server are now included under the /examples folder.

Test

Needs Chrome Installed.

npm install
npm install grunt-cli -g

npm test

jshint

npm install
npm install grunt-cli -g

grunt jshint

Minify

npm install
npm install grunt-cli -g

grunt uglify

License

MIT

How to contribute

pull requests welcome.

please use the following style guidelines

(http://nodeguide.com/style.html)

Contributors

Thanks

  • AngularJS Team
  • NodeJS Team
  • JavaScript Team

ngupload's People

Contributors

adebisi-fa avatar apolishch avatar cidevant avatar cristianocd avatar ctesene avatar dblanchard13 avatar devniel avatar dizzy7 avatar evan-r avatar hybriscole avatar jorgenfb avatar kelp404 avatar kunal999 avatar marek-stoj avatar mguymon avatar michaelakbaraly avatar mimo84 avatar nathankot avatar peerb avatar rockrep avatar siyfion avatar tvjg avatar twilson63 avatar wallin avatar whyjustin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ngupload's Issues

Documentation Slightly Wrong

In the documentation, it is specified that the callback for the submit action should take the arguments contents and completed, when it should really be "content" as opposed to "contents" to work properly.

Content from crossdomain iframe empty?

Hello,
first of all, thanks for that great module. Really makes life easier!

However I have some trouble retrieving the content from the iframe. The thing is that my application is talking to a RESTful PHP backend on a different domain. For all the ajax calls I use withCredentials = true.
So when I name that same backend for the action inside my form the iframe is populated with the correct contents but they can't be retrieved because of this error:

Unsafe JavaScript attempt to access frame with URL https:/backend.com 
from frame with URL http://frontend.com. The frame requesting access  
has a protocol of 'http', the frame being accessed has a protocol of  
'https'. Protocols must match.

To avoid this I already tried to redirect the whole request to a php file on the frontend domain which then saves the file and sends a new request to the backend. But with this method my sessions on the backend are not there anymore.

I'd appreciate any help.

Kind regards,
Denyo

Usage example is wrong

With current implementation the form should have an id and the id should be passed as the first argument of the submit function.

 <form action="/api/v1/me/photo" id="avatarUpload">
    <input type="file" name="file">
    <button ng-click="uploadAvatar()">Upload</button>
  </form>
$scope.uploadAvatar = function() {
        upload.submit("avatarUpload", function(content){
            // handle response back....

        });
    };

ngUpload Availability on NuGet

I'm currently working on publishing ngUpload to NuGet under the AngujarJS.ngUpload package id.

Will send a pull request as soon as completed.

You don't have permission to access /uploads/ on this server

Hi, as a first time user....

....struggling with this error:

Forbidden

You don't have permission to access /uploads/ on this server.

Apache Server at app.openpsychotherapy.org Port 80

I have created a folder "uploads" with permissons: 755 / 777

Hmmm? Any Idea?

Here is my Ctrl:

function ngUploadCtrl($scope, $rootScope) {
  console.log('----------- ngUploadCtrl -----------');
    $scope.uploadComplete = function (content, completed) {
    if (completed && content.length > 0) {
      $scope.response = JSON.parse(content); // Presumed content is a json string!
      $scope.response.style = {
        color: $scope.response.color,
        "font-weight": "bold"
      };

      // Clear form (reason for using the 'ng-model' directive on the input elements)
      // $scope.fullname = '';
      // $scope.gender = '';
      // $scope.color = '';
      // Look for way to clear the input[type=file] element  =>  FOUND SOLUTION?
    }
  };
}

And my HTML:

  <div ng-controller="ngUploadCtrl">
   <form action="/uploads" ng-upload> 
     <input type="file" name="avatar"></input>
     <input type="submit" value="Upload" 
       upload-submit="results(content, completed)"></input>
   </form>
 </div>

...

<script src="/js/ng-upload.js"></script>

EDIT 1:

Do I have to declare an app module, add ngUload?

angular.module('myApp',['ngUload']);

=> Now I see a uploading (the folder 'uploads' is still empty).... then my console tells me:

GET http://app.openpsychotherapy.org/uploads/?_t=1371715661256 403 (Forbidden) 

EDIT 2:

I have put this .htaccess file into uploads directory:

Options +Indexes 
# or #
IndexIgnore *

Now - no more 403 (Forbidden) error - the directory is still empty.

What am I doing wrong?
Thanks for any helpful suggestions!

Cross-domain support?

I have no idea whether this is actually even possible, but at the moment I'm in a situation where ngUpload is the only thing causing me a problem with this. 😟

I have an AngularJS single page application that interacts extensively with a REST API server, the website itself is served over HTTP and the API server is accessed entirely over HTTPS (and on a different domain). As part of the functionality the API server supports, it allows me to upload images as part of multipart/form-data, for which I'm trying to use ngUpload to send the file, however, I get the following error:

Blocked a frame with origin "http://mydomain.com" from accessing a frame with origin "https://api.mydomain.com". The frame requesting access has a protocol of "http", the frame being accessed has a protocol of "https". Protocols must match.

The server supports CORS requests and seems to work for all my other "normal" requests, eg. $http.get('https://api.mydomain.com/users'), I was just wondering if there was any way around this? Or am I going to have to use the HTML5 File API to read the file client-side and send it as part of an AJAX request..?

Version mismatch heads-up

mismatch The version specified in the bower.json of package ngUpload mismatches the tag (0.3.9 vs 0.3.8)
mismatch You should report this problem to the package author

Feature request: Initiate file upload right after selection from dialog box

Hi, I've been able to get the ngUpload directive up and running very smoothly so thanks for all the effort put into this.

Now, I've read about some custom JS logic that is applied in order to start file upload as soon as selection from the dialog occurs... leveraging the onchange event or something.

Is it possible to have the ngUpload directive accept a flag that would enable this feature?

Some bug fixes and suggestions

  • Bug: The generated iFrame is disposed before the form's first submit, thereby making the form submit to a new tab/window, instead of the inner frame.
  • Suggestion: Current implementation cannot submit a form multiple times, as the form get removed from the DOM after the first submission. A new iframe should be created at each submit and disposed after reading the response.)
  • Suggestion: Allow other html elements, apart from <input type='submit' />, be able to submit a form. Should be able to submit a form with an image, a link, a div, custom elements, among others.
  • Suggestion: Allow some configurable options on the ng-upload directive. For example, allows enabling/disabling of submission elements (input[type=submit], divs, a, img, etc), during and after upload, respectively.

I'm planning a pull request that solves all these, with some more examples on usage.

Hope this helps.

Is it possible to use with an ajax call, rather than a form post?

Is it possible to somehow achieve the same thing without using a form submit, perhaps with a wired up ng-click?

ie. Say I have the following:

<form ng-upload> 
    <input type="file" name="avatar"></input>
    <input type="submit" value="Upload" upload-submit="results(content, completed)" ng-click="sendTheFormData()"></input>
</form>

"express": "3.2.0" on example

So I tried to run this with the package.json you had, and I was not able to do it, so I changed from "express": "~3.1.0" to "express": "3.2.0" and started working, weird :S, I can push this if your are ok with that.

Regards,

Alberto Cole

I'm using node 0.8.4 btw.

How can I add validation in ng-upload

Because I can't controll the ng-submit action, I don't know how to add validations for fields other than file field.Normally I add validation in ng-submit in the forms which not using ng-upload.
This is not an issue..But I don't know where to ask these kinda questions

Incorrect version information on ReadMe

Reporting v0.1.1 as v0.2.0 is not correct. The current version v0.2.1 is the previous v0.2.0.

If there's going to be a v0.2.1, it should be clearer (with examples, and usage scenario), the bug it's fixing, the problem it's trying to solve, or the feature it's introducing.

Enhancement: Additional parameter for callback functions to indicate upload operation state

Currently, the callback function accepts only a single string parameter. During upload, the argument passed for this parameter can be any of the following:

  • The status of the upload process, e.g. "Please wait...";
  • An empty string (noticed on Google Chrome, immediately the iFrame is added to the DOM);
  • The real response from the server.

To differentiate real response from progress information, I'll suggest an additional boolean parameter be added to the callback function to indicate the nature of the content.

The following rule will help callback content consumers. Whenever the boolean parameter is:

  • True: Content can be process as report from server;
  • False: Content is just progress information, and can be displayed, but not processed;
  • Null or Undefined should be taken as False;

Going by the above, callback functions can then be written as:

$scope.callback = function (
           content /* string */, 
           isCompleted /* boolean */
) {
 ...
} 

or

$scope.subObject = {
    callback: function (
             content /* string */, 
             isCompleted /* boolean */
    ) {
        ...
    },
   /* other object properties */ 

A prototype of this feature is on the way.

Any further suggestions?

ASP.Net Web API and callback

Although I am receiving the file data @ my Web API server-side controller and I return an HTTP OK message, the upload-submit callback never fires when the upload is finished (although it gets fired during/before submission).
It could be something at the server-side. In your latest ChangeLog you mention Web API sources under your "examples" folder. Where can I find them? (they are not there at the master branch)

Feature Request:

Canceling the upload request would be awesome - I imagine something like removing the iframe from the dom?, for large file uploads this would be important.

$event is not defined

HI,
I ran the nodejs example and got this:
"Uncaught ReferenceError: $event is not defined " (ng-upload.js:35).
Could anyone please explain what happen on the server side? How can I save the file the public folder on example 5?
Thanks,
Trang

Post method accept:application/json

Based on #43, I'm trying to Post a Url, but always response with WARN: XHR response is not valid json. If I Post using accept: application/json, I don't have any trouble, I'm testing this on Fiddler Web Debugger. So, It's possible to set this on the html code:

Upload with Anchor

Here ->

is possible set accept:application/json here? or Does exist another way to do this?

Please, Help me.

Add Tests

TODO Need to add testacular tests..

Set header attribute

Hello,

I need to set a header attribute in my POST request in order to send a token to an API. Is it possible to do that ?

Thanks

Hard-coded upload button title

The HTML title for the upload button (upload trigger element) is hard-coded in the directive as "'Click to start upload." and "(enabled ? '[ENABLED]: ' : '[DISABLED]: ') + 'Uploading, please wait...'". This prevents customization/internationalization. It would be better to have no title at all set via the ngUpload directive than have it hard-coded.

Feature request: required attribute for input[type=file]

I want to validate my form before submission by disabling the submit button when no file is provided.

<input type="submit"  ng-disabled="!form.$valid" upload-submit="uploadComplete(content, completed)" />

Here is a directive that provides such a feature, however when you have included jquery it throws an exception, not sure why.

.directive('validFile',function(){
    return {
        require:'ngModel',
        link:function(scope,el,attrs,ngModel){
          //change event is fired when file is selected
            el.bind('change',function(){
                    scope.$apply(function(){
                        ngModel.$setViewValue(el.val());
                        ngModel.$render();
                    });
            });
        }
    };
})

here is a plunkr: http://plnkr.co/edit/C5j5e0JyMjt9vUopLDHc?p=preview

Upload without file?

Hi Tom,

as I told you earlier, I would like to combine blog-awesome with ng-upload. So my first attempt was to switch the post form to upload form. Is it true that the form would only work if a file/image is attached? I made all input field not required but without a file, no action is taken.
I know ng-upload is written with upload in mind, I thought it'd be nice to integrate it in a blog post form but file upload rather an option than obligation.

Thanks, Trang

allow using data-prefixed attributes

Using data-ng-upload instead of ng-upload does not work, given that the form is found using:

// submit the form - requires jQuery
var form = element.parents('form[ng-upload]') || element.parents('form.ng-upload');

jQuery Dependency Version

Is there any chance you could see if jQuery v.1.10.2 is compatible and if so, allow it in your bower dependencies list? As ngUpload is the only module I use that is reporting a v1.10.2 incompatibility.

How to get server response?

Is there any way that this controller could be made to get the response from the server after the upload?

The use case for this would be to let the server relay messages to the client, such as failures (file too big, file wrong format,etc).

Callback functions parsing failure.

Callback function is not correctly parsed whenever the expression supplied to upload-submit doesn't match functionName(content, completed):

For example, the following PASSED:

<input type='submit' upload-submit='bar(content, completed)' />

while alll the following FAILED:

<input type='submit' upload-submit='bar(iframeText, completionStatus)' />
<input type='submit' upload-submit='bar()' />
<input type='submit' upload-submit='bar' />

I'll write out all the failing tests, and a probable workaround in a pull request.

Action on form causes full page refresh

By default, AngularJS will do synchronous page refresh on form submit if an action attribute is included on the form. This is exactly the behavior I'm seeing. Am I missing something? All the examples include an action...

Response JSON is surrounded with HTML...?

I am using ngUpload to sent an image to the server, after which the server sends back a JSON object containing the image's ID and filename. The issue is the response I get is like this:

"<pre style="word-wrap: break-word; white-space: pre-wrap;">[
  {
    "_id": "51c2bac6b9c53fa200d4b9eb",
    "filename": "Blue4_Large.svg"
  }
]</pre>"

Which obviously cannot be run thought JSON.parse() without issues.

I did have this working, so I think a recent update to ngUpload may have broken this for me. Any idea why this is occurring? If so, is there an easy way I can fix this?

Form appended to upload content

Hi,

As of this pull request, the content that gets passed on to the callback is screwed. Because the form is cloned into the body of the iframe, the form itself is parsed (body.innerText) and passed along to the callback.

Doesn't seem right to me. I tried to provide a fix myself, but I don't understand the code from that pull request. Why would you want to clone the form into the body of the iframe?

Submitting the form without clicking

Hello.

Great tool! I noticed that you handle the submission based on the click event on the submit button, but what about if the form is submitted another way? Say pressing the enter key on a form element? Is that handled as well?

Use this without using Action attribute

I've been messing with this but I can't seem to figure how to make it work with ng-submit on the form tag or ng-click on a button rather than action on the form tag. Is this possible or will it require a completely new directive?

Set request headers for REST authentication

Hi,great directive!.I am working on an angular app featuring basic REST CRUD operations.Problem is,my create action features an image upload(along with other text fields),and the REST API authenticates the requests with custom headers.With ajax this is no problem,you can set custom headers on the client,but with iframe technique that your directive uses-this is a problem.Do you have any idea on how to solve this?Thanks in advance!

Using ng-form instead of form

Hi Tom, I don't know if it's exactly and issue, but the upload don't work when using ng-form instead of the tag form.

I've tested in the aspnet.mvc example, and when I debug i noted that after the call of submit of the library the API is not called.

Do you know if it's possible to do that? I'am using AngularJs with Asp.Net WebForm, so I can't have another form in the page...

FF adding <pre> tags to the content of the iframe

I just stumbled upon this from testing with FF, seems FF is adding <pre> tags to the json response, so it turns into <pre>{ blah: true}</pre>.

i believe it is related to this issue - https://bugzilla.mozilla.org/show_bug.cgi?id=674186 The ticket suggests using .textContent instead of .innerHTML. I am not sure of the ramifications of using either. My quick fix is to manually chop the pre off

   // There is a pre at the start of content, gj FF
   if (content.indexOf('<pre>') == 0) {
       content = content.substring(5, content.length);
   }

   // There is a pre at the end of content, gj FF
   if ((content.length - content.indexOf('</pre>')) == 6 ) {
       content = content.substring(0, content.length - 6);
   }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.