4

I'll try to make my question as simple and clear as possible. So i recently read the .prop() vs .attr() page on the stackoverflow, and decided i'd start using prop() instead of attr().

HTML

<form action="php/select.php" method="POST" class="ajax">
    <fieldset>
        <legend>Show</legend>
        <div>
            <input type="submit" value="Show Servers"/>
        </div>
        <div id="output"></div>
    </fieldset>
    <input type="hidden" name="action" value="SHOW_SERVERS"/>
</form>

JQuery

$(document).ready(function(){
    $("form.ajax").on("submit",function(e){
        e.preventDefault();
        var t=$(this);
        var form=t.serialize();
        var method=t.prop("method");
        var url=t.prop("action");//Before: t.attr("action");
        console.log(url);
    });
});

Here comes the weird part, when i submit that form, what it prints in the console is this

enter image description here

My question is then:

Why does JQuery return an input element rather than the value of the form action property?

Why can .prop() get the value of the method attribute, but not the action attribute

PS: I already know the input has the property name="action".

Community
  • 1
  • 1
131
  • 1,363
  • 1
  • 12
  • 32

4 Answers4

4

Why does JQuery return an input element rather than the value of the form action property?

It has got nothing to do with jQuery as such.

It is the specification of HTML itself. The controls in a form are submitted with the form and the name of the control becomes the property of the form. More here: http://www.w3.org/TR/html401/interact/forms.html#control-name

This is different from an attribute which is on the form tag.

So, without even using jQuery, if you were to refer to an input element called example, you would do that as formname.example.

Fiddle: https://jsfiddle.net/abhitalks/jct8ksr3/

Snippet:

$("form.ajax").on("submit",function(e){
 e.preventDefault();
 console.log(this.example);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="php/select.php" method="POST" class="ajax">
  <div>
    <input type="text" name="example" value="test"/>
    <input type="submit" value="Show Servers"/>
  </div>
</form>

What jQuery does is that it exposes the attributes with attr. These return the attribute values (of the tag) which actually do not change from the source. However, jQuery also exposes the properties of an element (the current values of the tag attributes included). And because the form control names are attached as properties to the form, it will return those as well.

You may see that by just logging this in your code:

console.log(t);
Abhitalks
  • 27,721
  • 5
  • 58
  • 81
1

The method attribute is not for boolean value. You need to use attr() for this. The prop() should be used only for setting and resetting boolean values like disabled or checked.

$(document).ready(function(){
    $("form.ajax").on("submit",function(e){
        e.preventDefault();
        var t=$(this);
        var form=t.serialize();
        var method=t.attr("method");  // Change here
        var url=t.attr("action");     // Change here
        console.log(url);
    });
});

FYI, prop() is not a replacement for attr(). Consider this:

<input type="checkbox" name="chkBox" checked="checked" id="chkBox" />

Use:

$("#chkBox").prop("checked"); // true
$("#chkBox").attr("name");    // chkBox

With the same code, I guess it should work:

$(document).ready(function() {
  $("form.ajax").on("submit", function(e) {
    e.preventDefault();
    var t = $(this);
    var form = t.serialize();
    var method = t.attr("method");
    var url = t.attr("action");
    console.log(url);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form action="php/select.php" method="POST" class="ajax">
  <fieldset>
    <legend>Show</legend>
    <div>
      <input type="submit" value="Show Servers" />
    </div>
    <div id="output"></div>
  </fieldset>
  <input type="hidden" name="action" value="SHOW_SERVERS" />
</form>

I can see php/select.php in the Console.

The reason why it returns the <input /> is, as said by Álvaro González, (I don't wanna take that credit), it is because if there's <input name="something">, then the <form>.something will be a property of the form. So prop() got confused with the same name and action.

For more information, see named form fields become properties of parent form.

Community
  • 1
  • 1
Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
1

As you may have already suspected, confusion comes from the fact that you've used the word "action" twice in your code:

<form action="php/select.php" method="POST" class="ajax">
      ^^^^^^
<input type="hidden" name="action" value="SHOW_SERVERS"/>
                           ^^^^^^

Since jQuery 1.6, t.attr("action") fetches HTML attributes exclusively and t.prop("action") fetches, well, JavaScript properties. So:

This is a pretty good example of why the new logic helps avoid ambiguity.

Álvaro González
  • 142,137
  • 41
  • 261
  • 360
  • 1
    Ah!!! Man, I guessed it. But didn't strike. I was about to write the answer quoting it here: https://github.com/jquery/jquery/blob/master/src/attributes/prop.js. – Praveen Kumar Purushothaman Dec 30 '15 at 09:16
  • so what is the difference between these `checked="checked"` and `checked`? – Jai Dec 30 '15 at 09:17
  • @Jai In what context? Whatever, we have the HTML attribute and the JavaScript property. In the case of "checked", the HTML attribute works by being present or not (its value is a **string** and is not relevant) and the JavaScript property is a **boolean**. – Álvaro González Dec 30 '15 at 09:20
  • I know you had the answer first, but i better liked his explanation. No offense ^.^. Thank you for the answer though! – 131 Dec 30 '15 at 09:26
  • 2
    This is not a speed contest, it's a collective knowledge base ;-) – Álvaro González Dec 30 '15 at 09:28
0

Looking in jQuery source code (line 8239 in jquery-1.11.3.js), you can see that the prop function relies (after several checks) on calling the given element field.

In your example, the element is the form and the fields you are trying to get are method and action. It returns 'post' for method, because method is a proper field of the form (the DOM object), so form[method] returns 'post' as expected. Now regarding action, there's no action field in the form (the DOM object), so calling form[action] in fact triggers an underlying mechanism that ultimately returns the first element in the form that has action as its name attribute: the input you see in the console.

Samuel
  • 2,106
  • 1
  • 17
  • 27