Hi, Habr!
I want to share with the public my small (only 6 Kbytes)
js-library , which greatly facilitates my work with forms when developing websites, and allows us to reduce the writing of code.
In any, more or less medium and large project, there are more than one dozen forms, many of which it is desirable to send via AJAX. Often a handler is just hung up for this and a script is written, something like this:
$(function () { $('.contact-submit').click(function () { $.ajax({ url: '/path/to/action', method: 'post', data: $(this).closest('form').serialize(), success: function () { } }); }); });
And everything seems to work, but, unfortunately, developers often forget little things, such as:
- no indication of form submission;
- as a result, the ability to click multiple requests (re-sending is not blocked);
- the inability to send the form from the keyboard;
- no indication when the form is sent to an error (for example, the server responded with a 500th error);
- controller's hardcode url in js-script.
In addition, there are many subtleties that are not taken into account in most similar libraries, such as: sending the
name=value
button that sends the form, supporting
<input type="image">
and the
form, formaction, formmethod
.
And taking into account that there are a lot of forms in large projects, then such handlers for each type of forms as a result form a significant amount of code. But often, the forms are quite simple, such as the “feedback form”, we just need to send the form and show the status - a letter has been sent or an error has occurred. With the help of the library described in this article, it is possible not to write code for such simple forms at all.
I will begin to describe the possibilities.
')
Support html5 attributes for older browsers
Due to the attributes
form, formaction, formmethod, formenctype, formtarget
you can flexibly change the behavior of form
form, formaction, formmethod, formenctype, formtarget
. The most common example is the selection of operations on a variety of objects selected by the user using the checkbox:
Sample code <div class="items"> <div class="item"> <input type="checkbox" form="mass"> <form action="/cart/add"> <input type="text" value="1"> <button type="submit"> </button> </form> </div> <div class="item"> <input type="checkbox" form="mass"> <form action="/cart/add"> <input type="text" value="1"> <button type="submit"> </button> </form> </div> ... <form id="mass" method="post"> <button type="submit" formaction="/controller/move"></button> <button type="submit" formaction="/controller/delete"></button> </form> </div>
With the
form
and
formaction
we were able to solve the problem of the impossibility of nested forms, as well as choosing the controller url depending on the action.
The library provides polyfill for browsers that do not support these attributes (IE <10).
DemoBlock re-sending and status display
I think many have met with this more than once, that the user presses the submit button several times, and as a result, instead of, for example, one comment, three identical ones are published at once. Very often, to avoid this effect, simply write a script that makes the send button disabled after clicking, forgetting that the form can still be sent from the keyboard.
The library also adds a
form-loading
class when the submission process takes place, thanks to which you can use CSS to hide this form state as you like.
If you still need the ability to resubmit the form before completing the previous one, then it is enough to add the
form-no-block
class.
DemoFiltering empty fields when sending
This feature can be useful for product search / filtering forms, in which there are many fields, in order to make the URL look more visually. Agree to see in the address bar better
example.com/?price_to=1000
than
example.com/?price_to=1000&price_to=&amount_from=&amount_to=
Just add a
form-no-empty
class to the form.
DemoAJAX form submission
This is perhaps one of the main functions of the library. Many plug-ins are able to send forms via AJAX, but unfortunately they do not send the form in the same way as the browser does. In particular, it supports the above-described html5 attributes of the
form
,
formaction
,
formmethod
, passing parameters of the active submit button and coordinates for
<input type="image">
. In order to submit the form via AJAX, you need to add the
form-ajax
CSS class to the form, and to display the result, add the
<output>
tag to an arbitrary place inside the form or another tag with the
form-output
class. You can specify an element outside the form, for this in the
data-form-output
attribute specify the jQuery-selector of this element. A similar attribute can be used in the root element of the response (it has a higher priority). And if the root element of the response has the
form-replace
CSS class, then the form itself will be used as the output element, and it will be replaced, which is very convenient for “one-off” forms. Consider this on the example of the feedback form:
Feedback Form Code <form action="/site/callback" method="post" class="form-ajax"> <div class="form-group"> <label></label> <input type="text" name="name"> </div> <div class="form-group"> <label>Email</label> <input type="text" name="email"> </div> <div class="form-group"> <label></label> <textarea name="message"></textarea> </div> <output></output> <button type="submit"></button> </form>
The algorithm is as follows - the form is sent via AJAX, and if it passes validation and there are no errors in the submission, then we deduce a Bootstrap Alert that everything is in order, and it will replace the form with itself. If there are any errors, we
<output>
them to the
<output>
. And note, there is not a single line of JavaScript. The library has support for Bootstrap Alert, so that it automatically makes
alert-dismissible
and adds a close button on its own.
For AJAX forms, the following events are generated:
formajaxbefore
- before submitting the form, allows you to change all the settings $.ajax
;formajaxdone
- in case of successful sending;formajaxfail
- in case of an error;formajaxalways
- in any case, after the completion of the AJAX request.
In general, this also makes it easier to write your scripts, because it allows you to hang the code directly on the event of a successful response, bypassing the routine with passing the URL and parameters. In events, you can cancel the default behavior of the script, it is enough to call
e.preventDefault()
- no manipulation of the output will not occur.
If, on the contrary, the loaded content is needed and, moreover, contains other components that need to be initialized (for example, datepicker). For this, the library generates two more events:
contentprepare
- before adding content to the DOM;contentinit
- after adding content to the DOM.
For myself, I concluded that it was easier for me to have the same procedure for initializing all plugins, so I came to this process:
$(function () { $(document).trigger('contentinit', [$(document)]); }); $(document).on('contentinit', function (e, cont) { cont.find('.datepicker').datepicker(); });
That is, when the page loads, we also generate a
contentinit
event, on which we hang a handler that initializes all the plugins.
DemoAJAX file sending
It is even more difficult to send a form with files without reloading the page, since obsolete browsers do not know this at all, and here you need an iframe method for emulating this process. Here I did not reinvent the wheel, and gave this functionality completely on the shoulders of the
malsup jquery.form plugin, leaving only one way to send it. On the server side, everything looks the same as if you sent the forms in the standard way.
To submit the form with the files, you need to connect the malsup jquery.form plugin and specify enctype = "multipart / form-data". For the form sent in this way, an event will additionally be generated:
formajaxprogress
is an event informing you of the current send status.
DemoAJAX Redirect
Another small useful little thing. To force the page to switch to a new one (make a redirect), simply enter the
X-Redirect
header, the value of which is the URL for the conversion.
DemoButton, for classic submission in AJAX-form
You can make it so that in an AJAX form there will be one or several buttons that send the form in the usual way. For example, I use it on the cart page - when the user changes the quantity of goods, then AJAX is used to save the changes. When he presses the “Go to checkout” button, the normal sending of the same form takes place.
DemoChange the appearance of the submit button
The library provides some more helpers to change the appearance of the submit button so that users understand that the form is in the process of sending. To do this, add a
btn-loading
CSS class to the button, and use one or both of the following options:
- attribute
data-loading-text
- changes the text of the button while submitting the form to the one specified in the attribute, and upon completion returns it; - The attribute
data-loading-icon
adds an icon to the button that indicates the loading process.
For example:
<button type="submit" class="btn btn-primary btn-loading" data-loading-icon="fa fa-refresh fa-spin">Submit</button> <button type="submit" class="btn btn-primary btn-loading" data-loading-icon="glyphicon glyphicon-refresh">Submit</button>
Additionally, for one or several buttons, you can specify the
btn-submit-default
class, then if the form is sent from the keyboard, the buttons will still change their appearance.
DemoAlerts for forms
Sometimes it is necessary to display some warnings or error messages to the user in the form, for example, validation errors. The library provides a simple interface for adding bootstrap alert-s to the form output element. Used as follows:
$('form').formAlert('! <b> </b>!', 'danger'); $('form').formAlert('#external-alert', 'success', true);
DemoConclusion
The library is available in the npm and bower repositories under the name
paulzi-form
:
bower install paulzi-form npm install paulzi-form
She is quite young, so I’m waiting for bug reports on the githaba. I would be glad if someone script also make life easier, like me.
GitHub project