AngularJS, Module object and form name - javascript

I having trouble to understand some weird problem, I will explain as sort as i can:
For example i got this form:
<form method="post" action="index.htm" name="chat" novalidate>
<label ng-show="chat.message.$error.pattern || chat.message.$error.required" for="message">Some error message</label>
<textarea ng-required="true" type="text" maxlength="200" id="message" name="message" ng-pattern="patterns.chatMessage" ng-model="chat.message"></textarea>
<input type="submit" value="send" ng-disabled="chat.$invalid">
</form>
Please note(because i didn't included all the code) that ng-pattern="patterns.chatMessage" patterns is a $rootScope property.
So when the page load i was expecting chat.message.$error.pattern to be false, But apparently unless i will set ng-model="some other object like client.message" or set ng-model="some other object property like chat.comment" When the page load chat.message.$error.pattern will be true, So basically if the model object.property is the same as the formName.textareaName i got this wierd problem.
In sort what is happen is that chat.message.$error.pattern is set to true from the moment the page load, If anyone can please explain what is the problem here i will be very thankful, Thank you all and have a nice day.

You cannot use the same scope variable in form's name tag and in your ng-model.
When you use a form tag in angular, and that tag has a name attribute (e.g. chat), the Angular will create an instance of ngFormController on current scope and will assign that instance to a variable as specified in name attribute (in this case chat).
If you use this very same scope variable chat to host your ng-model than your ngFormController (defined on $scope.chat) will become overwritten by your model and it will produce erratic results.
So, to fix things, you need to rename your form:
<form method="post" action="index.htm" name="chatForm" novalidate>
<label ng-show="chatForm.message.$error.pattern || chatForm.message.$error.required" for="message">Some error message</label>
<textarea ng-required="true" type="text" maxlength="200" id="message" name="message" ng-pattern="patterns.chatMessage" ng-model="chat.message"></textarea>
<input type="submit" value="send" ng-disabled="chatForm.$invalid">
</form>

Related

Why does my javascript function result in a rangeError?

Fairly new to this. I read a bunch of answers with people having a similar problem. I tried all the solutions offered (using e.stopPropagation, using e.stopImmediatePropagation, using id instead of tag...) but nothing worked. I deployed a single html page through firebase.
I wrote the script directly in the html. Here's my code:
function onclick(e) {
/*e.stopPropagation() and e.preventDefault() --YIELDD SAME RESULT*/
e.stopImmediatePropagation()
console.log("hello")
}
<h3>Please update your information below</h3>
<form id="login-form" class="reset-form">
<label>Email:</label>
<input name="email" type="email" placeholder="#">
<label>New Password:</label>
<input name="password" type="password">
<label>Confirm Password:</label>
<input name="second-password" type="password">
<button id="submit-button" type="button" onclick="onclick()">Update</button>
</form>
</div>
</body>
Desired behavior: on click, button with id logs a message in the devtools console.
p.s. I'm sure there's a basic mistake I'm making but I am not able to find which one. Please help!
onclick is the name of a common DOM property. When a function with this name exists in the Global scope (as yours does), it essentially becomes a property of the window object and can overwrite the Global one. Call your callback function something else or move it out of the Global scope and it will work.
Also, e.stopImmediatePropagation() is most likely not required for your use case.
Finally, nothing can come after </body> except </html>. <script> elements are allowed in the head and body, but no where else.
<h3>Please update your information below</h3>
<form id="login-form" class="reset-form">
<label>Email:</label>
<input name="email" type="email" placeholder="#">
<label>New Password:</label>
<input name="password" type="password">
<label>Confirm Password:</label>
<input name="second-password" type="password">
<button id="submit-button" type="button" onclick="onclick1()">Update</button>
</form>
<script>
function onclick1(e) {
console.log("hello")
}
</script>
Now, since you are just learning all this, let's make sure you get off on the right foot. There is soooo much bad HTML and JavaScript floating around and bad habits are still used today because most people don't know any better so they just copy/paste someone else's code that seems to work.
Don't use inline HTML event handlers (onclick, onmouseover, etc.) in the first place. Separate your JavaScript from your HTML and follow modern, standards based code. There are many reasons to not use inline HTML event handlers. Instead, use the .addEventListener() method.
Next, the <label> element is a semantic element that works in one of two ways:
It has a for attribute that has a value that is identical to the
form field that it is the label "for":
<label for="txtFirstName">First Name:</label>
<input id="txtFirstName">
It contains the form field element that is is a label for:
<label>First Name: <input id="txtFirstName"></label>
In either case, you are telling the client that there is a relationship between the label and the form field it is a label for. This allows a user to click or touch the label and activate the form field. It is also very helpful to those who rely on assistive technologies (like screen readers) to use the web.
So, putting all this together, your code reworked would look like this (I've added just a little CSS to make the page a little cleaner to look at, but none of that is required):
label { display:block; width:200px; margin-bottom:.5em; }
button { margin-top: 1em; font-size:1.2em; padding:5px; }
<h3>Please update your information below</h3>
<form id="login-form" class="reset-form">
<label>Email: <input name="email" type="email" placeholder="#"></label>
<label>New Password: <input name="password" type="password"></label>
<label>Confirm Password: <input name="second-password" type="password"></label>
<button id="submit-button" type="button">Update</button>
</form>
<script>
// get a reference to the DOM element you want to work with
let btn = document.getElementById("submit-button");
// configure the event handler in JavaScript, not in HTML
btn.addEventListener("click", logToConsole);
// give your functions meaningful names
function logToConsole(e) {
console.log("hello")
}
</script>
<button id="submit-button" type="button"
onclick="onclick()">Update</button> causes an infinite loop. You're overriding the onclick method which basically makes your code say "When I'm clicked, click me" ad infinitum.
Change the name of function onclick() to anything else, like function hello() and it'll work.
Here's a working codepen you can play with. https://codepen.io/anon/pen/mzajGd
I think it's best to change which event your stopping, which seems to be the form submit. Unsure why you're getting the range issue, but this should work.
<!DOCTYPE html>
<html>
<body>
<form id="login-form" class="reset-form" >
<label>Email:</label>
<input name="email" type="email" placeholder="#">
<label>New Password:</label>
<input name="password" type="password">
<label>Confirm Password:</label>
<input name="second-password" type="password">
<input type="submit">Update</button>
</form>
<script>
document.getElementById("login-form").addEventListener("submit", function(event){
event.preventDefault();
alert('boogy');
});
</script>
</body>
</html>
Hi Steve and welcome to Stack Overflow.
First place your Button, there are several ways to acomplish this:
<button class="ui-btn" id="cmdHello">Push Me</button>
Yet another Button
Now react to it's Click event:
<script type="application/javascript">
$(document).bind("pageinit", function() {
$(document).on("click", "#cmdHello", function(evt) {
console.log("Hello World");
});
});
</script>
That should do the trick.

How to get ElementRef reference from NgModel FormControl in NgForm in Angular 4+

In Angular 4+, I've following template driven form:
<form #addForm="ngForm" (ngSubmit)="onFormSubmit($event, addForm)" >
<div class="form-group">
<label for="item_name">Item Name</label>
<input id="item_name" name="item_name" [(ngModel)]="itemName"
#item_name="ngModel" autofocus class="form-control"
required minlength="4" maxlength="20"
aria-describedby="itemNameHelpBlock">
<small *ngIf="(item_name.invalid && item_name.touched)" id="itemNameHelpBlock" class="form-text text-error" >
Value must be at least 4 characters and must not exceed 20 characters
</small>
</div>
<div class="form-group">
<label for="item_type">Item Type</label>
<input id="item_type" name="item_type" [(ngModel)]="itemType"
#item_type="ngModel" class="form-control" required minlength="2"
maxlength="20" aria-describedby="itemTypeHelpBlock">
<small *ngIf="(item_type.invalid && item_type.touched)" id="itemTypeHelpBlock" class="form-text text-error" >
Value must be at least 2 characters and must not exceed 20 characters
</small>
</div>
<button class="btn btn-output-primary btn-lg" [disabled]="!addForm.form.valid">Add</button>
</form>
In the component section, I want to access the form field (ie item_name, item_type) as ElementRef so that I can access their corresponding DOM element through the nativeElement method of ElementRef class.
I've tried with #ViewChild but, it returns NgModel class object:
#ViewChild('item_name') item_name: ElementRef;
ngAfterViewInit() {
console.log(this.item_name); // it returns NgModel class object
}
But, I need to access the DOM HTMLElement of #item_name form field so that I can reset document focus to #item_name input field after every form submission. Now, I don't know how I can do it without directly accessing the DOM and I don't wanna directly access the DOM via DOM api.
I would be glad if I get some help here.
I would simply add read option to ViewChild query:
#ViewChild('item_name', { read: ElementRef }) item_name: ElementRef;
^^^^^^^^^^^^^^^
Stackblitz Example
See also
How to get reference of the component associated with ElementRef in Angular 2
Just to give a use case, you can point #item_name to ngModel to access some attributes of the model itself, for example if it's currently considered valid.
<input id="item_name" name="item_name" [(ngModel)]="itemName" #item_name="ngModel"
autofocus class="form-control">
<!-- here's where you can access the attributes if it's pointed to ngModel-->
<small [hidden]="password.valid">
The item name is not valid
</small>
If you don't need this rather fancy stuff, you can just remove it, as Andriy proposed. Then it's working out of the box with no further changes.
If you need to keep it however, you can give your input field an additional reference which you can use to get the ElementRef.
<input id="item_name" name="item_name" [(ngModel)]="itemName"
#item_name="ngModel" #itemNameField autofocus class="form-control">
You just have to reference the one that is not pointing to ngModel.
#ViewChild('itemNameField') itemNameField: ElementRef;
Angular does not complain about having multiple references on one field (as far as I tested it)
In your HTML, do not point template reference #item_name to ngModel, just leave it empty like:
<div class="form-group">
<label for="item_name">Item Name</label>
<input id="item_name"
class="form-control"
name="item_name"
[(ngModel)]="itemName"
#item_name
autofocus>
</div>
then, you can access DOM element using #ViewChild decorator (as you did) like:
this.item_name.nativeElement,
I noticed, you have a typo in your submit button: opening '[' is missing just before disabled property.
Plunker: https://plnkr.co/edit/XHqOiEBmuFrA3slZSlrD?p=preview

How to access Session value from Angularjs.?

i wants to access session value from angular js.or set it in a text field.But its not working.
<input type="text" id="uname" value="<%=session.getAttribute("username")%>" ng-model="username" readonly="readonly">
when i set the value of normal text field its working, like
<input type="text" id="uname" value="<%=session.getAttribute("username")%>" readonly="readonly">
but after adding ng-model its not working.
How i will do this?Please anybody help me.
It's angular's normal behavior. Try to use
ng-value="'<%=session.getAttribute("username")%>'" which is better
or
ng-init="username = '<%=session.getAttribute("username")%>'"

AngularJS form validatation of auto-generated form

I am trying to validate an auto-generated form (via AngularJS v1.3) which inputs' names are in format:
form_name[field_name]
The very basic example would be:
<form name="morgageCalculator">
<input type="text" class="form-control"
name="morgageCalculator[homeValue]" value="0"
data-ng-model="data.homeValue" required="required"/>
</form>
As you can see, the input name is morgageCalculator[homeValue]. Now I would like to add an error message below it:
<div class="error"
data-ng-show="!morgageCalculator.morgageCalculator[homeValue].$pristine && morgageCalculator.morgageCalculator[homeValue].$invalid">
Please enter a number
</div>
For very obvious syntax reasons this expression is not valid:
morgageCalculator.morgageCalculator[homeValue].$pristine
But this one also does not work:
morgageCalculator["morgageCalculator[homeValue]"].$pristine
So, the question, is there any sane way of accessing those fields? I wouldn't mind moving the validation to some controller function, but I was faced with same issue of inability to access field object.
Any help/hint would be greatly appreciated.
With help of #dfsq from comment section, I was able to find the error. Unlike my SO question, my code was missing data-ng-model.
Validation will not fire at all if input was not bound to model....
The correct snippet:
<form name="morgageCalculator">
<input type="text" class="form-control"
name="morgageCalculator[homeValue]" value="0"
data-ng-model="data.homeValue" required="required"/>
<div class="error"
data-ng-show="!morgageCalculator['morgageCalculator[homeValue]'].$pristine && morgageCalculator['morgageCalculator[homeValue]'].$invalid">
Please enter a number
</div>
</form>

Empty input onload even if it is saved in the navigator

I would like to clear all the input in my website even if the parameters for logging have been saved by the navigator.
I've tried to do that using that on the concerned input
<input type="text" name="login" placeholder="Adresse E-mail" onload="this.value=''">
Is there an other way for doing that?
What you might want to try use is the autocomplete=off parameter in your input fields.
<input type="text" name="login" placeholder="Adresse E-mail" autocomplete="off" >
This parameter can also be added to the actual <form> element -
<form name="myForm" id="myForm" method="post" autocomplete="off" >
To handle it in generic way, instead of tagging every field, use readystate change event of document and get all input elements by tag name using getElementsByTagName. Check the type of each element and then set the appropriate value.

Categories