i'm trying to do basic validation of the form fields in angular. It works properly when i inline the input field(s) with the form, however when I'm trying to use directives for inserting the input form field, the validation does not work as expected.
here is the JSbin showing the problem. I would appreciate some help thanks!
http://jsbin.com/sufotecenovi/2/edit
How Angular Validation Works
Angular uses the 'name' attribute to create the $scope variables used for validation.
For example, if you have an input field with a 'required' attribute:
<form name="myform">
<input name="firstname" ng-model="firstname" type="text" required/>
</form>
Then to access the validation properties on $scope, you would do:
var validationFailed = $scope.myform.firstname.$error.required;
Where $error is an object that has 'required' as a Boolean property.
In the 'required' directive, you would see something like this:
if(attrs.value == ''){
ngModel.$setValidity('required', true); // failed validation
} else {
ngModel.$setValidity('required', false); // passed validation
}
You can pass any string to $setValidity, and it will set the $error property for you. For example, if you did:
$setValidity('test', true)
Then there would be an $error property named 'test' and it would be set to true. You can then access the property like this:
$scope.myform.firstname.$error.test
Other validation properties that are available are:
$scope.myform.firstname.$valid
$scope.myform.firstname.$invalid
$scope.myform.firstname.$pristine
$scope.myform.$valid
$scope.myform.$invalid
$scope.myform.$pristine
Hope this helps to answer your question.
Click Here
you can use this code.
function MyCtrl($scope) {
$scope.formFields = [
{
name: 'firstName',
type: 'text'
},
{
name: 'email',
type: 'email'
}
];
}
myApp.directive("dynamicName",function($compile){
return {
restrict:"A",
terminal:true,
priority:1000,
link:function(scope,element,attrs){
element.attr('name', scope.$eval(attrs.dynamicName));
element.removeAttr("dynamic-name");
$compile(element)(scope);
}
};
});
<div ng-controller="MyCtrl">
<form name="myForm">
<p ng-repeat="field in formFields">
<input
dynamic-name="field.name"
type="{{ field.type }}"
placeholder="{{ field.name }}"
ng-model="field.value"
required
>
</p>
<code class="ie">
myForm.firstName.$valid = {{ myForm.firstName.$valid }}
</code>
<code class="ie">
myForm.email.$valid = {{ myForm.email.$valid }}
</code>
<code class="ie">
myForm.$valid = {{ myForm.$valid }}
</code>
<hr>
</form>
</div>
Related
I want to display data in red colour when email is invalid.
I have n no. of data, out of them some email ids are not validated.
I have used only dynamic class.
//ts file
email_regx = /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/;
if (this.data.email_id) {
this.email_regx = true;
} else {
this.email_regx = false;
}
//html file
<span [ngClass]="{'redClass': email_regx}">{{ data?.email_id }}</span>
//css
.redClass{ color: red}
At first, please think about using an input field instead.
I would recommend to use FormBuilder from Angular Forms.
It will help you with a lean template and make validation a lot easier.
Could look like:
// TS
contactForm: FormGroup;
constructor() {
this.contactForm = this.formBuilder.group({
email: [
'',
Validators.compose([
Validators.pattern('^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*#[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$'),
Validators.required,
])
]
});
The FormGroup called "contactForm" here holds one input field called "email".
The validation is for your email.
// Template
<form id="contactForm" [formGroup]="contactForm">
<ion-item lines="none" class="list-item">
<div>
<ion-label position="stacked"
[class.error]="contactForm.controls.email.value != undefined && !contactForm.controls.email.valid">
E-Mail *
</ion-label>
<ion-input id="email" type="email" formControlName="email"></ion-input>
</div>
</ion-item>
</form>
The important part here is the formControlName and the [formGroup] to connect to your ts´s validation.
The part [class.error] adds the class "error" to the label. You also could use that for your input field.
You are not using regex the right way. Have a look to this doc.
You can make a simple function to test your email and return a boolean.
Component ts file :
public isValidEmail(email: string): boolean {
return /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email);
}
html file :
<span [ngClass]="{'redClass': isValidEmail(data?.email_id)}">{{ data?.email_id }}</span>
I want to bind the full name = firstname + lastname.
I have seen this example in the w3 schools. But i am unable to understand it.
My question is how the function got called? It have any listeners?
Could someone please, shed some light on it, in detailed way. Sorry I am newbie..
My code is:
var application = angular.module('myTempApp', []);
application.controller('myController', function ($scope) {
$scope.myFirstName = "xxx";
$scope.myLastName = "yyy";
$scope.myFunction = function () {
alert('called');
$scope.myFullName = $scope.myFirstName + $scope.myLastName;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<div ng-app="myTempApp" ng-controller="myController">
<input type="text" ng-model="myFirstName" />
<input type="text" ng-model="myLastName" />
<input type="text" ng-model="myFullName" ng-bind="myFullName" />
<br />
{{ myFunction() }}
<br/>
data ::: {{2+2}}
</div>
</body>
Thanks in advance.
lets go step by step.
You are binding three literals and one function type variable. Whenever you write any variable (of any data type), it gets registered in the digest cycle of angularJS. So, firstName, lastName, fullName and myFunction gets registered in digest cycle. And every variable in digest cycle has a watcher.
Whenever a variable changes, angularJS checks through all variables registered in digest cycle and prints the latest value of each variable in the view.
so lets assume - if firstName is xxx and last name is yyy and you changed firstName to xx. Now angular will check both firstName and lastName and print the latest value of both of them.
Therefore, whenever you make any change to any scope variable, your binded function inside the angular expression gets called
If you want to update a variable depending on other could use $watch
var application = angular.module('myTempApp', []);
application.controller('myController', function ($scope) {
$scope.myFirstName = "xxx";
$scope.myLastName = "yyy";
$scope.myFunction = function () {
//alert('called');
$scope.myFullName = $scope.myFirstName + $scope.myLastName;
};
$scope.$watch("myFirstName + myLastName", $scope.myFunction);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<div ng-app="myTempApp" ng-controller="myController">
<input type="text" ng-model="myFirstName" />
<input type="text" ng-model="myLastName" />
<input type="text" ng-model="myFullName" ng-bind="myFullName" />
<br />
{{ myFunction() }}
<br/>
data ::: {{2+2}}
</div>
</body>
This might help.
function studentController($scope) {
$scope.student = {
firstName: "Mahesh",
lastName: "Parashar",
fullName: function() {
var studentObject;
studentObject = $scope.student;
return studentObject.firstName + " " + studentObject.lastName;
}
};
}
Enter first name: <input type="text" ng-model="student.firstName"><br>
Enter last name: <input type="text" ng-model="student.lastName"><br>
<br>
You are entering: {{student.fullName()}}
There two ways of binding data between the model (html and the controller the data into the $scope, ng-bind and {{ }}. What they do here is call {{ myFunction() }} ((which act like a listener), then every time is taking care of myFirstName and myLastName (so as they change, the new value is going to be save in $scope.myfullName, and render into the model)
I have an Angular article form that I'm populating using a service call. The problem is that, in order to get validation and data binding to work, I have to use $setViewValue and $render on each form input. What I'd like to do is simply set the data model for the form and then render the entire form somehow.
Here is a sample of what I have that works:
var _promise = articleService.getArticle($scope.params.articleId);
_promise.then(
function(data) {
$scope.articleForm.title.$setViewValue(data.item.title);
$scope.articleForm.title.$render();
$scope.articleForm.bodytext.$setViewValue(data.item.body);
$scope.articleForm.bodytext.$render();
$scope.articleForm.keywords.$setViewValue(data.item.keywords);
$scope.articleForm.keywords.$render();
},
function() {
$scope.setMessage('There was a network error. Try again later.', 'error');
}
);
The code below accomplishes the same result visually (just doesn't render bindings, like updating fields to dirty in validation):
var _promise = articleService.getArticle($scope.params.articleId);
_promise.then(
function(data) {
// $scope.article breakdown: article.title, article.body, article.keywords
$scope.article = angular.copy(data.item);
// some sort of complete form render???
},
function() {
$scope.setMessage('There was a network error. Try again later.', 'error');
}
);
HTML:
<form name="articleForm" novalidate role="form">
<!-- TITLE -->
<div class="form-group" ng-class="{ 'has-error' : (articleForm.title.$invalid && !articleForm.title.$pristine) || (submitted && articleForm.title.$pristine) }">
<label>Title</label>
<input type="text" name="title" ng-model="article.title" ng-minlength="3" required>
<p ng-show="(articleForm.title.$error.required && !articleForm.title.$pristine) || (submitted && articleForm.title.$pristine)" class="help-block">A title is required.</p>
<p ng-show="articleForm.title.$error.minlength" class="help-block">Title is too short.</p>
</div>
<!-- BODY -->
<div class="form-group" ng-class="{ 'has-error' : articleForm.bodytext.$invalid && !articleForm.bodytext.$pristine }">
<label>Article Body</label>
<div text-angular ng-model="article.body" ng-change="updateBody()" id="bodytext" name="bodytext"></div>
</div>
<!-- KEYWORDS -->
<div class="form-group" ng-class="{ 'has-error' : (articleForm.keywords.$invalid && !articleForm.keywords.$pristine) || (submitted && articleForm.keywords.$pristine) }">
<label>Keywords</label>
<input type="text" name="keywords" ng-model="article.keywords" ng-minlength="3" ng-maxlength="150" required>
<p ng-show="(articleForm.keywords.$error.required && !articleForm.keywords.$pristine) || (submitted && articleForm.keywords.$pristine)" class="help-block">At least one keyword is required.</p>
<p ng-show="articleForm.keywords.$error.minlength" class="help-block">Keywords is too short.</p>
<p ng-show="articleForm.keywords.$error.maxlength" class="help-block">Keywords is too long.</p>
</div>
</form>
I feel like there should a simple solution to this, since it's a common scenario, but I've searched high and low without a clear answer. Maybe I'm just approaching this the wrong way?
Well, I found a solution that works, but I don't think it's a better solution than just setting all the form fields individually. I'll post it here though, in case it helps anyone else in some way.
// set all the values via the angular model
$scope.article = angular.copy(data.item);
// without a timeout all the fields will still be unset (being asynchronous)
$timeout(function() {
// loop through all the form values
angular.forEach($scope.articleForm, function(value, key){
if(typeof value === 'object' && key !== '$error'){
// reset the view value and render, to process the updates on the form
$scope.articleForm[key].$setViewValue($scope.articleForm[key].$viewValue);
$scope.articleForm[key].$render();
}
});
});
i want to write a code of javascript with ember control to control the password and confirm password fields matching with the help of javascript .
if it is possible with emberjs please let me know i tried this one but its not working with me code.
http://jsfiddle.net/8MRcS/12/
I don't know when i put this code in my contorl than its not working perfectly in the signup control if i put this in app.js controller than its wokring but i need this inside the signup code.
here is my template code .
<script type="text/x-handlebars" data-template-name="signup">
<h2>Sign Up</h2>
{{outlet}}
<form {{action "submit" on="submit" }}>
<!-- //This connects to the controller, using the user object -->
<p><label>Name: {{input type="text" value=user.name required="true"}}</label></p>
<p><label>Username: {{input type="text" value=user.username required="true"}}</label></p>
<p><label>Password: {{input value=user.password type="password" id="password" required="true"}}</label></p>
<p><label>Confirm Password: {{input value=user.confirm type="password" id="confirm" required="true"}}</label></p>
</br>
<p><label>Email: {{input type="email" value=user.email required="true"}}</label></p>
<p><label>Address: {{input type="text" value=user.address required="true"}}</label></p>
<p><label>Age: {{input type="number" value=user.age required="true"}}</label></p>
<button id="submit" {{bind-attr disabled="cannot_submit"}}>Submit form</button>
<button {{action "clear"}}>Clear</button>
<p></p>
<button> {{#link-to 'login'}}Already member{{/link-to}}</button>
</form>
{{message}}
</script>
signup controller code.
App.SignupController = Ember.ObjectController.extend({
// User is the model used for binding the view and the controller
// If you look at the view, you will see user.username, and user.password being
// used as input values
// BTW this is a JavaScript object, (i.e in JSON)
user: {
//These values are just place holders for the moment
name: "",
username: "",
email: "",
address: "",
age: "",
password: "",
confirm: "",
},
// The functions called when and event is triggered from the view (i.e button click)
actions: {
// Action called when form is submitted, refer to form action attribute in view
submit: function() {
var self = this;
var submitUser = {};
submitUser.name = self.user.name;
submitUser.username = self.user.username;
submitUser.password = self.user.password;
submitUser.cpassword = self.user.confirm;
submitUser.email = self.user.email;
submitUser.address = self.user.address;
submitUser.age = self.user.age;
// This is the API call to the web services, it uses the user (this.user) to send
// the login info, and recives either the logged in user info, or an error
console.debug(this.user);
console.debug(this.submitUser);
$.post("http://herukoapp.com/users", JSON.stringify(this.user), function(data,status){
data = JSON.parse(data);
console.debug(data);
});
},
// Called when the clear button is clicked, see button tag in view
clear: function() {
this.set('user.name', "");
this.set('user.username', "");
this.set('user.password', "");
this.set('user.confirm', "");
this.set('user.email', "");
this.set('user.address', "");
this.set('user.age', "");
}
},
});
You can use a computed property to track whether user.password and user.confirm are the same.
In Coffeescript:
confirmSame: (->
password = #get('user.password')
confirm = #get('user.confirm')
if password == confirm
return true
else
return false
).property('user.password', 'user.confirm')
Or in regular javascript (I think):
confirmSame: function() {
password = this.get('user.password')
confirm = this.get('user.confirm')
if password == confirm
return true
else
return false
}.property('user.password', 'user.confirm')
You can do a conditional with this in your template:
{{#if confirmSame))
<div>Password and Confirm Password are the same</div>
{{else}}
<div>Password and Confirm Password are not the same</div>
{{/if}}
And in your submit action you can check for whether confirmSame is true or false:
Coffeescript:
if #get('confirmSame')
# do submit stuff
Or in javascript (I think):
if (this.get('confirmSame') == true)
// do submit stuff
I cannot get at a form value through $scope.form. In the view and Batarang I see that the form object has the right name for all fields, but no values. On the other hand, the value in the actual form field is correct, as is the $scope.mymodel.headline value (see example below).
Why would this happen?
Sample for 1 field follows. Batarang output:
{
mymodel: {
headline: My value
}
form: {
mymodel[headline]: { }
}
}
If I output {{form}} in the view it shows:
mymodel[headline]: { }
Controller code is very simple:
#mymodelCtrl = ['$scope', ($scope) ->
$scope.init = (mymodel) ->
$scope.mymodel = mymodel
]
Much simplified HTML:
<div id="new_mymodel" ng-controller="mymodelCtrl"
ng-init="init({'headline': 'my value'})" class="ng-scope">
<form action="/myurl" id="new_mymodel" method="post" name="form" role="form">
<input id="mymodel_headline" name="mymodel[headline]"
ng-model="mymodel.headline" ng-required="true" type="text">
<input type="submit">
</form>
</div>
UPDATE: At first I thought the accepted answer was wrong, but that was because of a side issue. But it is correct: the issue is that developer console and batarang and view were displaying something wrong, not that the field is empty. I needed to use $scope.form["mymodel[headline]"].$formVaue.
You can get it's value from
$scope.form['mymodel[headline]'].$modelValue
See this.