HTML form onsubmit passing this.id; yielding unexpected value - javascript

I'm working on a website and was experiencing this problem, so I simplified it as much as possible.
index.html:
<html>
<head></head>
<body>
<script type="text/javascript" src="test.js"></script>
<form id="myForm" onsubmit="log(this.id)">
<input name="id">
</form>
</body>
</html>
test.js:
function log(str){
console.log("str=" + str);
}
When I submit the form, I see this:
str=[object HTMLInputElement]
and when I change the value of name to anything but "id", I see the expected
str=myForm
I get the exact same behavior if I switch all instances of "name" and "id" in the code. In other words, it doesn't seem to be a particular limitation of either attribute, but something more general.
I'm running MAMP on OS X 10.8; experiencing problem in Firefox 22.0 and Chrome ver. 28.
Thanks in advance

The .id on form elements accesses form fields by their name. To get the ID attribute use this.getAttribute('id').

When you gave the input the name "id", log(this.id) translates to log(myForm.id) where id is a property of myForm, it is in fact the input child element. This is indicated by the [object HTMLInputElement] class name which appears.
When you name the input child control to something else this.id now refers to the forms id attribute.
The same logic applies when you switch "id" with "name" since you can refer to controls by either their name or id.

Well, that's because this.id is being interpreted as "the element with name id that belongs to the form", that's why you're receiving an [object HTMLInputElement] through the parameter. When there is no such input (i.e. when you name it differently), this.id is interpreted as the form id.

Related

AngularJS evaluate expression in "action" attribute

This afternoon I experienced a very strange behavior of AngularJS.
If an expression containing "//" is in "action" attribute of a form, then the angular gives interpolate error.
Please see the code below. If you run the code, the URL can be correctly displayed in all places except in "action" attribute.
<form
id="moodleform" target="my_iframe"
method="post" action="{{'http://www.someurl.com'}}"
style="{{'http://www.someurl.com'}}"
some-attr="{{'http://www.someurl.com'}}">
{{'http://www.someurl.com'}}
<input name="somefield" value="someValue"/>
<input type="submit" value="Submit">
Here is the Plunker that demonstrates this problem, if you inspect the form element, you can see the action attribute is empty and there is error in console saying $interpolate:interr
https://plnkr.co/edit/R2ypg6WWmro1WdrNy6mX?p=preview
Any idea, thank you all.
You need to use ng-action instead of just action attribute
I found the solution.
Here is the original stackoverflow post: Angular set form action based on variable in scope
basically, i need to use $sce service in my controller in order to have an url in "action" attribute.

how to log element in angular?

I am working on an Angular application and i have a view who is containing an iframe (The purpose of that iframe is just to display a login form).
Like my attempt to submit the form manually was unsuccessful, i tried to log the formular to check if i am really able to reach it but i am confused about how to do that...
the form inside the iframe have name attribute myForm
<iframe id="myIframe" name="myIframe" src="someUrl.com">
<html>
...
<form name="myForm" class="form" action="myAction()" method="post" onsubmit="myStuffToDO()">
...
...
</form>
...
</html>
</iframe>
So the way that i am trying to log the form in my controller is like that:
var iframeForm = angular.element.find('myForm');
console.log(iframeForm);
the result in hte console is that:
[]
I am really confused about how to do that so any help would be really kind.
.find('myForm') would find <myForm> tags, not tags with an attribute with the "myForm" value. .find('[name="myForm"]') is what you are looking for, but it won't work with the built-in element implementation because .find, as stated in the docs, is "Limited to lookups by tag name".
That means you'll need to also include jQuery in your project. Then Angular will use it instead of its jqLite implementation and complex selectors will work.
You can access using form name withing scope like below:
console.log($scope.formName);
You can access all elements by their names inside formName object.
from the page you can access angular element by angular.element+jquery selector
eg : angular.element("[name='myForm']")

Javascript concatenation error while adding form name using smarty

What's wrong in this, i want to pass the value to the field of the specific form
var formid = 'addtaskform{/literal}{$smarty.session.formno}{literal}';
document.formid.title.value = 'yeah';
i am getting this error
TypeError: document.getElementById(...) is null
There is no problem with concatenation in that case. You probably do something else wrong.
Look at the following example:
PHP file:
$_SESSION['formno'] = 5;
$smarty->display('test.tpl');
Smarty template file:
<input type="text" id="addtaskform5" value="5" />
<script type="text/javascript">
{literal}
var formid = 'addtaskform{/literal}{$smarty.session.formno}{literal}';
document.getElementById(formid).value = 'yeah';
{/literal}
</script>
It works fine. Value of input is changed from 5 to yeah
You most likely don't have a form element with the id formid in your site, at least it is not what you actually want to achieve.
What you are looking for is this:
document[formid].title.value = 'yeah';
document.formid (Dot Notation) : get the element with the id formid
document[formid] (Bracket Notation): get the element with the id that is stored in the value formid

HTML form attribute "name" not getting defined in Firefox

Below is the sample code in my JSP page:
<form name = loginform method = post action="">
<table class=registerTable>
<tr>
<td>Username:</td></tr>
<tr><td>
<input name=user type=text class=usnm required size=28 maxlength=35 autocomplete="off" onblur="validateUser()" onkeyup="checkUsernameAvailability(this.value)"><br></td></tr>
<tr><td>
<span id = uerrmsg class = error></span><br></td></tr>
</table>
</form>
When onblur=validateUser() is called the following code executes:
function validateUser(){
if(loginform.user.value.length<5){
document.getElementById("uerrmsg").innerHTML="minimum 5 characters";
return false;
}else{
document.getElementById("uerrmsg").innerHTML="";
return true;
}
}
Error Console in FF gives the following error
loginform is not defined
Please help me on this.
PS: Above code works in all other browser.
you can use input.getAttribute("name") to get name attribute of an input.
This works for almost all browsers.
By the way, if you use getElementById, you must populate "id" field of input.
You should be using document.loginform.
You don't need the form for this.
First give your input an id: id="user". Then you can access it using document.getElementById(), as you do with the element. something like this:
document.getElementById("user").value.length
Also, your code is very non-standard, for eg you should not put a " " (space) between the attribute (or it's value) and the = sign. And the attributes' values should be within quotes (Look at the source code of this page, for example).

How can I know the id of a JSF component so I can use in Javascript

Problem: Sometimes you will want to access a component from javascript with
getElementById, but id's are generated dynamically in JSF, so you
need a method of getting an objects id. I answer below on how you can do this.
Original Question:
I want to use some code like below. How can I reference the inputText JSF component in my Javascript?
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<title>Input Name Page</title>
<script type="javascript" >
function myFunc() {
// how can I get the contents of the inputText component below
alert("Your email address is: " + document.getElementById("emailAddress").value);
}
</script>
</head>
<h:body>
<f:view>
<h:form>
Please enter your email address:<br/>
<h:inputText id="emailAddresses" value="#{emailAddresses.emailAddressesStr}"/>
<h:commandButton onclick="myFunc()" action="results" value="Next"/>
</h:form>
</f:view>
</h:body>
</html>
Update: this post Client Identifiers in JSF2.0 discusses using a technique like:
<script type="javascript" >
function myFunc() {
alert("Your email address is: " + document.getElementById("#{myInptTxtId.clientId}").value);
}
</script>
<h:inputText id="myInptTxtId" value="backingBean.emailAddress"/>
<h:commandButton onclick="myFunc()" action="results" value="Next"/>
Suggesting that the attribute id on the inputText component
creates an object that can be accessed with EL using #{myInptTxtId},
in the above example. The article goes on to state that JSF 2.0 adds
the zero-argument getClientId() method to the UIComponent class.
Thereby allowing the #{myInptTxtId.clientId} construct suggested
above to get the actual generated id of the component.
Though in my tests this doesn't work. Can anyone else confirm/deny.
The answers suggested below suffer from drawback that the above
technique doesn't. So it would be good to know if the above technique
actually works.
You need to use exactly the ID as JSF has assigned in the generated HTML output. Rightclick the page in your webbrowser and choose View Source. That's exactly the HTML code which JS sees (you know, JS runs in webbrowser and intercepts on HTML DOM tree).
Given a
<h:form>
<h:inputText id="emailAddresses" ... />
It'll look something like this:
<form id="j_id0">
<input type="text" id="j_id0:emailAddress" ... />
Where j_id0 is the generated ID of the generated HTML <form> element.
You'd rather give all JSF NamingContainer components a fixed id so that JSF don't autogenerate them. The <h:form> is one of them.
<h:form id="formId">
<h:inputText id="emailAddresses" value="#{emailAddresses.emailAddressesStr}"/>
This way the form won't get an autogenerated ID like j_id0 and the input field will get a fixed ID of formId:emailAddress. You can then just reference it as such in JS.
var input = document.getElementById('formId:emailAddress');
From that point on you can continue using JS code as usual. E.g. getting value via input.value.
See also:
How to select JSF components using jQuery?
Update as per your update: you misunderstood the blog article. The special #{component} reference refers to the current component where the EL expression is been evaluated and this works only inside any of the attributes of the component itself. Whatever you want can also be achieved as follows:
var input = document.getElementById('#{emailAddress.clientId}');
with (note the binding to the view, you should absolutely not bind it to a bean)
<h:inputText binding="#{emailAddress}" />
but that's plain ugly. Better use the following approach wherein you pass the generated HTML DOM element as JavaScript this reference to the function
<h:inputText onclick="show(this)" />
with
function show(input) {
alert(input.value);
}
If you're using jQuery, you can even go a step further by abstracting them using a style class as marker interface
<h:inputText styleClass="someMarkerClass" />
with
$(document).on("click", ".someMarkerClass", function() {
var $input = $(this);
alert($input.val());
});
Answer: So this is the technique I'm happiest with. Doesn't require doing too much weird stuff to figure out the id of a component. Remember the whole point of this is so you can know the id of a component from anywhere on your page, not just from the actual component itself. This is key. I press a button, launch javascript function, and it should be able to access any other component, not just the one that launched it.
This solution doesn't require any 'right-click' and see what the id is. That type of solution is brittle, as the id is dynamically generated and if I change the page I'll have to go through that nonsense each time.
Bind the component to a backing bean.
Reference the bound component wherever you want.
So here is a sample of how that can be done.
Assumptions: I have an *.xhtml page (could be *.jsp) and I have defined a backing bean. I'm also using JSF 2.0.
*.xhtml page
<script>
function myFunc() {
var inputText = document.getElementById("#{backBean.emailAddyInputText.clientId}")
alert("The email address is: " + inputText.value );
}
</script>
<h:inputText binding="#{backBean.emailAddyInputText}"/>
<h:commandButton onclick="myFunc()" action="results" value="Next"/>
BackBean.java
UIInput emailAddyInputText;
Make sure to create your getter/setter for this property too.
Id is dynamically generated, so you should define names for all parent elements to avoid j_id123-like ids.
Note that if you use jQuery to select element - than you should use double slash before colon:
jQuery("my-form-id\\:my-text-input-block\\:my-input-id")
instead of:
jQuery("my-form-id:my-text-input-block:my-input-id")
In case of Richfaces you can use el expression on jsf page:
#{rich:element('native-jsf-input-id')}
to select javascript element, for example:
#{rich:element('native-jsf-input-id')}.value = "Enter something here";
You can view the HTML source when this is generated and see what the id is set to, so you can use that in your JavaScript. As it's in a form it is probably prepending the form id to it.
I know this is not the JSF way but if you want to avoid the ID pain you can set a special CSS class for the selector. Just make sure to use a good name so that when someone reads the class name it is clear that it was used for this purpose.
<h:inputText id="emailAddresses" class="emailAddressesForSelector"...
In your JavaScript:
jQuery('.emailAddressesForSelector');
Of course you would still have to manually manage class name uniqueness.
I do think this is maintainable as long as you do not use this in reusable components. In that case you could generate the class names using a convention.
<h:form id="myform">
<h:inputText id="name" value="#{beanClass.name}"
a:placeholder="Enter Client Title"> </h:inputText>
</h:form>
This is a small example of jsf. Now I will write javascript code to get the value of the above jsf component:
var x = document.getElementById('myform:name').value; //here x will be of string type
var y= parseInt(x,10); //here we converted x into Integer type and can do the
//arithmetic operations as well

Categories