I'm new to angular so bear with me. I have a form with a dropdown, textbox and a button. The user has to select an option from the dropbox and enter a value in the textbox before the form becomes valid.
<form name='personDataSourceForm' novalidate ng-submit='personDataSourceForm.$valid && PersonCtrl.SaveDataItem()'>
<span>Invalid: {{personDataSourceForm.$invalid}}</span><br />
<span>valid: {{personDataSourceForm.$valid}}</span>
<div class="input-group">
<div class="input-group-addon">
<select class="form-control input-sm" required ng-model='PersonCtrl.sp.person.newItem.dataType' ng-options='opt as opt.text group by opt.dataType for opt in PersonCtrl.DataItemTypes'>
<option value="" disabled selected>Choose...</option>
</select>
</div>
<input type="text" class="form-control input-sm" ng-model='PersonCtrl.sp.person.newItem.value' required>
<div class="input-group-btn">
<button class="btn btn-default btn-sm" ng-class="{ 'btn-success' : PersonCtrl.sp.person.newItem.dataType.dataType && PersonCtrl.sp.person.newItem.value }" type="submit">Save</button>
<button class="btn btn-link btn-sm" type="button" ng-click="PersonCtrl.StopAddItem()">Cancel</button></div>
</div>
</form>
I quickly added 2 spans to show the validation state. When both are empty the form shows invalid which makes sense.
As soon as I type in a value in the textbox then suddenly the form is valid even though the dropdown still hasn't been changed.
Why is my dropdown not getting validated? I've even tried this solution AngularJS Dropdown required validation
My initial thought is that you already have that default value selected:
<option value="" selected>Choose...</option>
so it does technically have a value of "", which is fulfilling the required.
I think you will need to look at PersonCtrl.sp.person.newItem. The form becomes valid when both the dataType and value get solid. My guess is the item always has its dataType solid and valid so when the new value is entered the whole form becomes valid.
Why don't your select ad input have a name attribute? The name attribute is necessary for form validations to work properly.
I think form creates a map of name->validity for each input component and it could be that you have omitted it they both (select and input) map to the same validity object. If this is the case, then anyone becomes valid, effectively makes the status of the other one valid as well and hence they are both valid the form becomes valid.
Please add separate names for them and see if the problem is resolved. My opinion above is a strong guess and I have not dived into Angular code to check ng-form's behaviour.
Related
I tried many answers here at Stackoverflow, but none of them working:
<form ng-submit="runIt(cars)">
<input type="radio" ng-model="cars.erp" value="Toyota" ng-required="!cars.erp">Toyota
<br>
<input type="radio" ng-model="cars.erp" value="Nissan" ng-required="!cars.erp">Nissan
<br>
<input type="radio" ng-model="cars.erp" value="Honda" ng-required="!cars.erp">Honda
<br>
<input type="radio" ng-model="cars.erp" value="Other" ng-required="!cars.erp">Other
<input type="text" ng-model="cars.other" ng-show="cars.erp=='Other'" ng-required="!cars.other">
<br>
<input type="submit">
</form>
It all starts working only after typing a value in Other. Apparently, this is due to hidden input, but this is how it should work:
A value must be submitted,
If Other selected, value must be typed.
Here's the fiddle: http://jsfiddle.net/ADukg/17426/
To reproduce:
Run
Select Toyota
Click Submit
See Console in Inspect
The reason for the specific error you're getting of "invalid form control with name='' is not focusable" is because the browser wants to focus on the form element that is required(the text input), but the element is not visible.
<input type="text" ng-model="cars.other" ng-show="cars.erp=='Other'" ng-required="!cars.other">
You're saying that the text field is only required if cars.other evaluates to false. In other words, you're saying that the text field is required whenever it isn't filled out. What you actually want is for the text field to be required if cars.erp is set to other.
<input type="text" ng-model="cars.other" ng-show="cars.erp=='Other'" ng-required="cars.erp=='Other'">
Your text field's ng-model is cars.other and then you are checking for ng-required="!cars.other" which isn't right. You are requiring the text field with it self. Instead it should be dependent on the value of the radio button. Something like ng-required="cars.erp=='Other'".
I have updated the JSFiddle here -> http://jsfiddle.net/d0o29hb2/3/. Hope this helps.
I am a novice in angular. I am confused by $dirty and $invalid, they almost sound the same.
What is the difference between $dirty and $invalid used in email ng-model? Below is the scenario. It's an example form W3Schools.
<form ng-app="myApp" ng-controller="validateCtrl" name="myForm" novalidate>
<p>
Username:<br>
<input type="text" name="user" ng-model="user" required>
<span style="color: red" ng-show="myForm.user.$dirty && myForm.user.$invalid">
<span ng-show="myForm.user.$error.required">Username is required.</span>
</span>
</p>
<p>
Email:<br>
<input type="email" name="emaill" ng-model="email" required>
<span style="color: red" ng-show="myForm.email.$dirty && myForm.email.$invalid">
<span ng-show="myForm.email.$error.required">Email is required.</span>
<span ng-show="myForm.email.$error.email">Invalid email address.</span>
</span>
</p>
<p>
<input type="submit" ng-click="Count()"
ng-disabled="myForm.$invalid" title="Submit" value="Submit">
</p>
</form>
EDIT 1:
I am wondering if I change the ng-model name from email to email8 it's not working anymore.
<input type="email" name="emaill" ng-model="email8" required>
Whether the validation is doing by myForm HTML element name which is not defined using ng attribute. How does it work?
ng-show="myForm.email.$dirty && myForm.email.$invalid"
$dirty: It will be TRUE, if the user has already interacted with the form.
$invalid: It will be TRUE, if at least one containing form and control is invalid.
Source
Also on Angular Docs
After the update in the Question...The validation is being done on the form element name. All the ng-models inside a form is tracked and that is how it is working.
Also changing a ng-model name will have no impact on validation. I tried your link and it works for me. That has to work.
$dirty means the user has changed the input value, $invalid means the address itself is invalid. Therefore the error is only shown if the user has actively changed the input value to either an empty or invalid value.
$dirty is True if user has already interacted with input. And $invalid is true if the the input is not a valid email address
$error is the object of errors where the key is the field validation name and value is the actual error message
<input type="email" name="emailName" ng-model="email" required>
for this example myForm.emailName.$error.email = true if email is not matched with format.
myForm.emailName.$error.required = true if you haven't added anyhting in input field
you can check valid or not of the field directly by using myForm.emailName.$valid but
the problem in your case is they want to show the user what is the error by having two cases. so they entered into $error object to check for the error is required email or invalid email
1.Email is required.
2.Invalid email address.
so they used $error object.
this is how myForm.emailName looks:
{"$viewValue":"ss","$validators":{},"$asyncValidators":{},"$parsers":[],"$formatters":[null],"$viewChangeListeners":[],"$untouched":false,"$touched":true,"$pristine":false,"$dirty":true,"$valid":false,"$invalid":true,"$error":{"email":true},"$name":"emailName","$options":null}
I think the example provide by you explains a lot.
You have done mistake That is why it was not working , can you see below code which you have written
<pre>
<input type="email" name="emaill" ng-model="email8" required>
<ng-show="myForm.email.$dirty && myForm.email.$invalid">
</pre>
Why it was not working because input name you have given "emaill" and in myForm.email.$dirty you have given "email" If both names should be same then it will work fine
<pre>
<input type="email" name="emaill" ng-model="email8" required>
<ng-show="myForm.emaill.$dirty && myForm.emaill.$invalid"></pre>
I have a form with many fields, including several datepickers (Angular UI Bootstrap).
<div name="mainForm" ng-form>
<div class="form-group">
<p class="input-group">
<input type="text" name="dt"
class="form-control"
ng-model="dt"
is-open="opened"
datepicker-popup="MM/dd/yyyy" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
<p class="text-danger" ng-show="mainForm.$invalid">Invalid!</p>
</div>
I'm using Angular validation w/ the form. We have some required fields, but the dates are not. If you enter a date and remove it, it marks the form invalid. I created a Plunkr to demonstrate this.
Is there a way around this?
Note: It also logs this error in the console when you clear the date out.
Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.
In the current version of the code there is a $datepickerSuppressError value that you can set to true which will hide the console error. You can see in the code that it checks if the date is NaN and then displays the console error if $datepickerSuppressError is still false.
However, having said that, there is still a way to work around the issue of the form being invalid. You will just need to add an additional check to see if mainForm.$error.date is set, or something similar to this.
For example you can change your button to have this instead:
ng-disabled="mainForm.$invalid && !mainForm.$error.date"
Which will leave your button enabled even though the directive has set an error on the date and it should disable if any other field is invalid.
Friends, I am new to angularjs please explain why name attribute required for angularjs validation
<form name="lform" novalidate>
<input type="text" name="userName" ng-model="userName" required novalidate/>
<span style="color:red" ng-show="lform.userName.$dirty && lform.userName.$invalid">
<span ng-show="lform.userName.$error.required">Username is required.</span>
</span>
<br/>
</form>
If I remove name="userName" code not working, please explain this.
Update: If I remove "ng-model" it is not working, but I can change "ngmodel='newName'" is working, please explain this reason also.
This is just how HTML form works, name describe the parameter that will be sent to the server.
Angular's approach is to extend HTML and its behaviour, instead of inventing the wheel. Angular encapsulates "form" (see ngForm directive) and extend it. Because name is the unique id of an input in a form, it is also the unique id of the input in ngForm's collection.
ng-model is another directive that bind the value of the input into a variable in the current scope, it doesn't have to hold the same value as name.
Let's take your example and change ng-model:
<form name="lform" novalidate>
<input type="text" name="userName" ng-model="object.name" required novalidate/>
<span style="color:red" ng-show="lform.userName.$dirty && lform.userName.$invalid">
<span ng-show="lform.userName.$error.required">Username is required.</span>
</span>
<br/>
</form>
The validation will work, but the variable that will be updated in your scope is "object.name".
To sum it up, lform.userName holds the metadata and object.name will hold the actual data.
The answer is in your code.
<span ng-show="lform.userName.$error.required">Username is required.</span>
Angular is using the input name to store the error related information.
lform – your form name
username – your input name
I am trying to submit the form on only successful validation.
validation is working for required but not working for ng-minlength
form input is invalid but form is still being submitted.
<form name="myForm" ng-submit="count = count + 1" ng-init="count=0" ng-app>
<div class="control-group" ng-class="{error: myForm.mobile.$invalid}">
<label class="control-label" for="mobile">Mobile</label>
<div class="controls">
<input type="text" name="mobile" placeholder="07XXXXXXXXX" ng-model="mobile" ng-minlength="11" required />
<span ng-show="myForm.mobile.$error.required" class="help-inline">Required</span>
<span ng-show="myForm.mobile.$error.minlength" class="help-inline">Mobile number should be minimum 11 character starting from 07</span>
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn" type="submit" value ="submit" />
</div>
count: {{count}}<br />
<tt>myForm.$invalid = {{myForm.$invalid}}</tt><br/>
</div>
</form>
http://jsfiddle.net/pMMke/9/
what am I doing wrong.
I don't want to use submit button disable method.
This is what you are doing wrong: you are mixing two concepts, Angular validators and
HTML5 validators.
The required HTML5 validators, for instance, states that:
When present, it specifies that an input field must be filled out before submitting the form.
So, if you try to submit a form that has an input with this attribute, it will show a message explaining this to the user, and it will prevent the form from being sent. This is the behavior you want. Why isn't working for ng-minlength? Because ng-minlength is an Angular validator (you can tell because it begins with ng-), and it doesn't add any special behavior to the form. It simply set the input where it is located to invalid (and hence, the form), and let you decide what to do with it.
You have an option: you can use the pattern HTML5 validator, to specify the field requires at least 11 characters. It would like this:
<input type="text" pattern=".{11,}">
So when you submit a form containing this input, it will no be sent if the user has enter less than 11 characters.
But since we are it, and you are already using the pattern validator, you could use the regular expression in its full potential, and define something like:
<input type="text" pattern="07[0-9]{9}" />
Which will only admit values of 11 characters, that start by "07" and that contains only digits. I have modified your fiddle to show you how it would work: http://jsfiddle.net/helara/w35SQ/
I mistakenly used ngMaxlength="12" ngMinlength="6" instead of ng-minlength="6" ng-maxlength="12", it's working fine now.
Both ng-minlength & mg-maxlength works in AngularJS.
I've tested this in AngularJS version 1.3.
Make sure to use novalidate with <form> to disable browser's native validation.
This should work:
To enter mobile number
ng-show="myForm.mobile.$touched && myForm.mobile.$error.required"
For minimum length
ng-show="myForm.mobile.$touched && myForm.mobile.$error.minlength"
For maximum length
ng-show="myForm.mobile.$touched && myForm.mobile.$error.maxlength"
This work for me guys
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input ng-minlength="11" class="mdl-textfield__input" type="text" name="cpf" id="cpf" ng-model="avaliacao.cpf" ng-required="true" ng-pattern="/^\d+$/">
<label class="mdl-textfield__label" for="cpf">CPF *</label>
</div>
<p style="color: #d50000;" ng-show="myForm.cpf.$error.required && myForm.cpf.$dirty">Field Required</p>
<p style="color: #d50000;" ng-show="myForm.cpf.$error.pattern">Only numbers</p>
<p style="color: #d50000;" ng-show="myForm.cpf.$error.minlength">Min 11 Chars</p>
I'm facing the same issue, and I think you can only disable the button or ignore the entered value by yourself. You can also check the $valid property in your controller and ignore the value... It is not so nice, but I found no other way.