Using closest for getting form object - javascript

Recently, I am reviewing client side code written by another programmer. I am surprised with code which is used for getting form object.
HTML for Login Form
<form id="frm_login" action="">
<input type="text" name="username" id="username">
<input type="password" name="pwd" id="pwd">
</form>
He has used following code to get form object
$frm = $("input[type='password']").closest("form");
But there is simple code for getting form object which I prefer:
$frm = $("#frm_login");
Is there any reason to use closest to get form object in above scenario?
I would really like to know if there is any performance issues.

The id of element is supposed to be unique. If there is single form on page then there is no need to relate it to its parent using closest. It would have more sense if the form does not have id. Getting form through id seem more straight forward and fast.
If there are multiple forms and one have to get the form in which the element exists then using closest make sense. This could be understood with the following example.
Live Demo
Html
<form id="frm_login1" action="">
<input type="text" name="username" id="username1" />
<input type="password" name="pwd" id="pwd1">
<table>
<tr>
<td>
<input type="text" class="myInputClass" />
</td>
</tr>
</table>
</form>
<form id="frm_login2" action="">
<input type="text" name="username" id="username2">
<input type="password" name="pwd" id="pwd2">
<table>
<tr>
<td>
<input type="text" class="myInputClass" />
</td>
</tr>
</table>
</form>
Javascript
$("input[type='password']").closest("form").each(function(){
alert($(this).find('.myInputClass').val());
});

If there is single form on page then there is no need to relate it to its parent using closest. It would have more sense if the form does not have id. Getting form through id seem more straight forward and fast.
But The Closest() method is very cool and very useful, especially when you start to deal with event delegation in which events are trapped at a higher level in the node tree than are the elements that triggered the event.
the closest() method searches through these elements and their ancestors in the DOM tree and constructs a new jQuery object from the matching elements.

as others said, if you have id, no need to use closest to get parent form. and using id is faster.
HOWEVER, in some cases you need to use closest to get form, for example, if you write a universal function for validating every password input in every form, in this case you don't like to get forms by ids and search for its childes passwordfields to prevent auto submitting, so i guess the guy who wrote the code, is doing this(a function which validates passwords before submit)
$("input[type='password']").each(function(){
$frm = .closest("form");
$frm.submit(function(event){
if( not valid password){
......
return false;
}
});
});

Related

Why not able to submit a non-rendered form?

Is there a way to submit a non-rendered form?
I have specific scenario where I want to submit a dynamic form to the server. As of now I have achieved this by adding form to the body after creating it using jQuery. It works perfectly, but I wonder why I am not able to submit a in memory form without rendering into the DOM.
Following is the code snippet I have tried:
var action_url = "/post-url";
$(`
<form action=${action_url} method="POST">
<input type="text" value="name1" name="name1"/>
<input type="text" value="name2" name="name2"/>
<input type="text" value="name3" name="name3"/>
</form>
`).appendTo('body').submit();
So, why I am not able to do like below:
var action_url = "/post-url";
$(`
<form action=${action_url} method="POST">
<input type="text" value="name1" name="name1"/>
<input type="text" value="name2" name="name2"/>
<input type="text" value="name3" name="name3"/>
</form>
`).submit();
When I run the above code getting following warning message in console:
Form submission canceled because the form is not connected
When we attempt to insert elements into the document, it would create some DOM nodes cached by document fragments before appending to the document. The nodes cached by document fragments CAN register event handlers and also CAN be triggered, but submit()'s algorithm would be a little different.
DOM nodes in document fragment are NOT part of the active document tree structure and according to the HTML standard documentation, if the form is not connected (associated, created or whatever else similar term) to the browsing context(document), the submission process will be canceled.
For further reading:
Form submission algorithm
DocumentFragment
A form should be on the DOM before submission because afterloading page, every element is attached an event so is recognized by the DOM and jquery or javascript can manipulate. but what you are doing (2nd) doesn't even exist in the DOM so the event submit() is not available to it.

Input value not passing to URL

I have a total of two input values. Only one value passes to the url of the next page, but both should. What's causing this?
JSFiddle: http://jsfiddle.net/p8dCC/
HTML:
<!--form action="device" onSubmit=" get_search(); return false;" id="search-form-4" method="get" target="_top"-->
<div class="fix">Brand</div>
<input class="inputs" type="text" id="search_id" name="q3" placeholder="Send this" required="required" />
<br/><br/>
<div class="fix">Model</div>
<input class="inputs" type="text" id="search_id" name="q4" placeholder="And send this one too" required="required" />
<br/><br/>
<input id="search-button" class="" type="submit" value="continue" data-target="http://www.google.com/?item-description" />
<!--/form-->
You have two elements with the same id in html. So when you do this $('#search_id').val() only one of them will get evaluated and not both. Ids are supposed to be unique
After testing your code in a test page, I found that both inputs were in fact being passed through the URL.
You have commented out the form tags which I'm not sure if you did just for purposes on here.
kjs is correct as well, though using the same id would only effect the HTML. Using get as the method would bypass this issue as it would be passed the unique "name" attribute.
A form tag is required if you expect the html submission mechanism to work correctly on its own.
In the Javascript you posted though, you are treating document.location as an html element, wrapping it with jquery, then trying to use jquery's attr method on it. This won't work. Just access "location.href" directly without using jquery.
Additionally, as pointed out by another answer, your ids should all be unique.

AngularJS forms not finding input elements

At some point during the development of my app, AngularJS forms stopped working... Yes that means they used to work. That is, form elements are supposed to create their own scope with every <input /> by their name. However all my forms are now completely empty, as if I had no input elements with the name attribute. Now I can't make any sort of form validation. I've tried even the most trivial forms and still nothing:
<form name="form>
<input type="text" name="input" required />
</form>
Any suggestions as to how to debug this?
Hi to do validation your input have to have model directive please see here: http://jsbin.com/deref/1/edit
<form name="form">
<input type="text" name="foo" required ng-model="input.model"/>
<span ng-show="form.foo.$error.required">required</span>
</form>
Try console.log on the scope
console.log($scope.form);
If you have your controllers set up correctly, your form should be attached to the scope of controller.

angularjs form input suggestions

I have a problem with a form in angularjs.
Example with classic html & php
<form name="myForm" action="post.php" method="post" autocomplete="on">
<input name="namename" type="text" />
<input name="email" type="text" />
<input name="submit" type="submit" value="submit" />
</form>
which works as expected. On the second visit, after i submitted the form for the first time, i just need to type the first letter and the input field will suggest something based on the first post.
The same form in angular.
<form name="myForm" ng-submit="test(user)" autocomplete="on">
<input name="name" type="text" ng-model="user.name" autocomplete="given-name" />
<input name="email" type="text" ng-model="user.email" />
<input name="submit" type="submit" value="submit" />
</form>
On the second visit here the form will suggest nothing at all, which is very irritating.
Is there any fix for that?
Example
thanks in advance.
That behaviour you're describing is done by the browser and is not guaranteed to work in all situations. It's actually quite easy to do in AngularJS; just keep track of a shared state object. This can be done in several ways, the most easiest by using the value provider like this:
// Create an injectable object with the name 'userInput'
angular.module('myApp').value('userInput', {});
Now inject this object in the controller that is handling the form like this:
angular.module('myApp').controller('MyController', function($scope, userInput) {
// Assign the state object to the scope so it's available for our view
$scope.user = userInput;
});
Render the form as you did and you'll see that the state of the form is kept. In fact, this is one of the hidden gems when programming with Angular since it allows you to keep very complex state information, which was previously pretty impractical.
Live demo can be found in this plunker.
Edit
One way to get the autocomplete to work is to maintain datalist elements. Just store the previous entered values in an array and use a ng-repeat to render all the options. Associate the input element with the datalist using the list attribute and you'r good to go.
<input list="nameHistory" type="text" ng-model="user.name" />
<datalist id="nameHistory">
<option ng-repeat="item in userHistory.name" value="{{ item }}"></option>
</datalist>
Live demo can be found in this plunker.
Just add to the input tag this attribute autocomplete="off"

Validating individual elements using jQuery Validation

I am using JQuery validation plugin jquery.validate for validating my form inputs in this manner like this:
<form id="loginForm" name="loginForm" action="" method="POST">
<input name="username" type="text" />
<input name="password" type="password" />
<input type="submit" value="Login!" />
</form>
</div>
<script>
$("#loginForm").validate({ rules: { username: "required", password: "required" } });
While above works fine, I also needed input validation for elements which are not inside a form and they are being sent to the server dynamically using jQuery etc. so my question is, is it possible to validate such individual elements which are not inside form elements using jQuery Validation, like these:
<tr>
<td><label>Product Name</label></td>
<td colspan="2">
<select name="prdNme" id="prdNme" placeholder="Enter Product Name..." >
<option data-id='' data-pnme='' data-price='' value=''></option>
</select></td>
</tr>
<tr>
<td><label>Quantity</label></td>
<td colspan="2">
<input type="text" style="width: 80px" placeholder="Quantity" id="qntty" /></td>
</tr>
If yes than how? and if no than how can i validate them without writing my whole new validating functions?
Quote OP:
"... I also needed input validation for elements which are not inside a form ... so my question is, is it possible to validate such individual
elements which are not inside form elements using jQuery Validation"
No. It is not possible to validate any input elements not contained within <form></form> tags using the jQuery Validate plugin.
All input elements must be contained within form tags and .validate() attached to the form element to initialize the plugin. There is no other way. This is by design.
See: documentation...
"Validate forms like you've never been validating before!"
Quote OP:
"if no, then how can I validate them without writing my whole new validating functions?"
Why would you need to re-write anything? Simply wrap your input elements within a set of <form></form> tags.

Categories

Resources