Felipe Pelá
Felipe Pelá

Reputation: 171

How to do just the input file of a form submit a file and the others fields not?

whats up?

There are a lot of examples in the Internet about make a ajax-jquery form to upload an image. like this:

<form id="imageform" method="post" enctype="multipart/form-data" action='ajaximage.php'> 
<input type="file" name="photoimg" id="photoimg" />
</form>

Make this form upload a file is not so difficult, but I need something else.

I have a form a little bigger than that.

Example:

<form id="imageform" method="post" enctype="multipart/form-data" action='ajaximage.php'> 
<input type="file" name="photoimg" id="photoimg" />
<input type="text" name="foo"/>
<input type="text" name="bar"/>
<input type="submit" value="FINALLY DO THE SUBMIT"/>
</form>

Whats the big deal?

Well, I want the file input field do the upload of the file onchange event. But I dont want that the hole form do the submit. There are others fields to be done and after all the user will do the final submit.

I have no problem to do that in back end, my PHP engine is waiting and working, but I have no ideia of how to do that in front end.

Any sugestions?

Upvotes: 2

Views: 638

Answers (3)

DfKimera
DfKimera

Reputation: 2146

You can use the target attribute of the <form> element to submit the form without reloading the page. The extra fields will still be sent, but by dynamically swapping the <form> attributes, such as action and enctype, you can ensure the file input will be sent to an point in your back-end.

I have written a simple JavaScript+jQuery component that allows you to quickly setup AJAX uploaders. It will handle the attribute changes automatically and lets your back-end trigger a callback in your front-end:

var uploader = {

    functionBegin: function () {},
    functionCallback: function () {},

    formID: '',
    formAction: '',

    buttonID: '',

    originalAction: '',
    originalTarget: '',
    originalEnctype: '',
    originalOnSubmit: '',

    isSetup: false,

    // Initializes the AJAX uploader
    init: function(formID, buttonID, formAction, beginFunction, callbackFunction) {

        // Sets up the optional callback functions
        this.functionBegin = beginFunction;
        this.functionCallback = callbackFunction;

        // Sets up the selectors and upload form atributes
        this.formID = formID;
        this.buttonID = buttonID;
        this.formAction = formAction;

        // If we haven't already, create the invisible IFRAME that our form will target
        if(!this.isSetup) {
            $(formID).append('<iframe id="AU_IFrame" name="AU_IFrame" src="about:blank" style="width:0;height:0;border:0px solid #fff;"></iframe>');
            this.isSetup = true;
        }

        // If a button selector was defined, we hook it's click event
        if(buttonID) {
            $(buttonID).click(function () {
                uploader.triggerBegin();
                return false;
            });
        }

    },

    // Begins the file upload
    triggerBegin: function() {

        // Backs up the original form attributes
        this.originalAction = $(this.formID).attr('action');
        this.originalTarget = $(this.formID).attr('target');
        this.originalEnctype = $(this.formID).attr('enctype');
        this.originalOnSubmit = $(this.formID).attr('onSubmit');

        // Sets up the form with our upload attributes
        $(this.formID).attr('action', this.formAction);
        $(this.formID).attr('target', 'AU_IFrame');
        $(this.formID).attr('enctype', 'multipart/form-data');

        // Call our 'on upload begin' callback, if defined
        if(this.functionBegin) {
            this.functionBegin();
        }

        // Submit the upload form
        $(this.formID).submit();

        // Now that it's already uploaded, revert back to the original attributes
        $(this.formID).attr('action', this.originalAction);
        $(this.formID).attr('target', this.originalTarget);
        $(this.formID).attr('enctype', this.originalEnctype);
        $(this.formID).attr('onSubmit', this.originalOnSubmit);

    },

    // This can be called from the back-end, will trigger the user-defined callback
    triggerCallback: function(params) {
        if(this.functionCallback) {
            this.functionCallback(params);
        }
    }


};

Here's an example on how you would apply this in an HTML form:

<form name="test" method="POST" action="regularForm.php">
    <input id="fileInput" name="fileInput" type="file" />
    <input type="text" name="foo" />
    <input type="text" name="bar" />
    <input type="submit" value="Send" />
</form>

<script type="text/javascript">
    $(function () {

        uploader.init(
            '#fileInput', // File field selector
            null, // Upload button selector (Optional, since we'll upload on change, this won't be needed here)
            'fileUpload.php', // Upload action
            function () { // Callback on upload begin (optional)
                alert("Starting upload!");
            }, 
            function (params) { // Callback on upload end/error (called by the back-end, optional)
                alert("Upload successful");
            }
        );

        $('#fileInput').change( upload.triggerBegin ); // automatically upload on file input change

    });
</script>

To trigger the callback properly, just make sure your back-end will run the following (assuming you're using PHP):

$someParameter = "whatever you want to return in the callback";

echo '<script type="text/javascript">';
echo 'if(top.uploader && top.uploader.triggerCallback) { top.uploader.triggerCallback("'.$someParameter.'"); }';
echo '</script>';

You can naturally tweak the parameters to make it return, for example, the file URL, upload status, size, etc.

As for other solutions, without HTML5 the only alternative is to use a Flash/Silverlight/Java applet or the Google Gears plugin, that will handle the file picking and uploading. There are a bunch of jQuery plugins that implement all of the alternatives as gradual fallbacks:

Upvotes: 1

Cesar Canassa
Cesar Canassa

Reputation: 20173

In order to submit a file via javascript you must first read its content. Unfortunately it's impossible to do that with HTML4, the HTML4 doesn't have any API that reads local files.

But there is a workaround for that, basically you need to redirect a form's action into a hidden IFrame. So, when the form with the file field is submitted, the result will appear in a IFrame. But since it is hidden, the user will not see it. This effect is achieved using the 'target' attribute of the Form tag.

HTML:

<iframe id="blah"></iframe>
<form id="imageform" target="blah" method="post" enctype="multipart/form-data" action='ajaximage.php'> 
    <input type="file" name="photoimg"/>
    <input type="text" name="foo"/>
    <input type="text" name="bar"/>

    <input type="submit" value="FINALLY DO THE SUBMIT"/>
</form>

Javascript:

$('#imageform input').change(function () {
    // This is called when any input changes
    $(this)
        .siblings()
            .attr('disabled', '')  // Disable the other inputs
        .end()
            .parent()
                .submit() // Submit the form
            .end()
        .siblings()
            .removeAttr('disabled'); // Re-enable the inputs
});

Of course, if you don't want to write all that stuff, you could just use a jQuery plugin

Upvotes: 1

Adriano Silva
Adriano Silva

Reputation: 2576

This tutorial can help you http://rafaelcouto.com.br/upload-dinamico-com-php-jquery/

Upvotes: 1

Related Questions