Access Angular Model Validation Without A Form - angularjs

I'm looking to do use some of the validation features in an Angular Directive that I am building up. However, the directive may or may not be inside of a form. Is there a way to access the validation status of a model without trying to access the state of a form?
My template is along the lines of....
<select id="{{$id}}key" ng-model="newItem.key"
ng-options="key as key.label for key in tableKeys" required>
</select>
<span class="error" ng-show="newItem.key.$error.required">Required!</span>
<input id="{{$id}}value" type="text" ng-model="form.newItem.value" required/>
<span class="error" ng-show="newItem.value.$error.required">Required!</span>
<button ng-click="addItem()">Add Item</button>
(Not seeing any validation messages here)
On top of it, I want to addItem to check the state of validation as well
$scope.addItem = function(){
if(<do something to check validation>)
{
<do some other thing>
}
Any help would be much appreciated!
Thanks,
Andrew

My understanding is that you want to avoid using the form.xyz.$error attributes for error checking.
I do not know how to do it using a directive, but I do know how to do it using the controller.
In that case, you can use the $scope.$watch function on your model.
It would be something like this:-
1.) In your controller,
$scope.$watch('newItem.key',function(){
if( <condition to validate> ==true)
{
$scope.selectError ="errorMessage";
}
});
2.) In your HTML
<select id="{{$id}}key" ng-model="newItem.key"
ng-options="key as key.label for key in tableKeys" required>
</select>
<span class="error" ng-show="selectError">{{selectError}}</span>
Note: This is only for the select element. You can bind the text input to a model, and do the same for it as well.
The $scope.$watch function will watch out for any changes to the specified model, and will execute the accompanying code whenever any change occurs.

Related

Angular - Watching a form whether its $dirty - performance

In my Angular app, I'm setting the placeholders in my form through some code in the controller (showing particular text for particular times of day).
When a user begins typing into any field of that form, I want all placeholders to be cleared.
To do this I understand I need to use $dirty using $watch
$scope.$watch('myForm.$dirty', function() {
//clear the placeholders
}, true);
My question is watch quite performance intensive in this situation or is there a more optimised way?
Thanks.
If you use $dirty and $watch it will work but it will clear all placeholders before you begins type or on controller load.
So, you can try this its work for me.
<div ng-controller="Ctrl">
<input type="text" ng-model="name1" ng-change="change()" placeholder={{placeholder1}}>
<input type="text" ng-model="name2" ng-change="change()" placeholder={{placeholder2}}>
<input type="text" ng-model="name3" ng-change="change()" placeholder={{placeholder3}}>
</div>
function Ctrl($scope) {
$scope.placeholder1="name";
$scope.placeholder2="city";
$scope.placeholder3="address";
$scope.change=function() {
$scope.placeholder1="";
$scope.placeholder2="";
$scope.placeholder3="";
};
}

Detecting value change in ng-model without using $watch and form for application having large number of models

My application has a lot of models in the page. I want to detect whether user has changed value of any model on click of save. Using $watch on every model puts too much load, so don't want to use this method. Is there any good approach for this?
Small snippet is like below:
<div>
<div class="ttere2">
<input type="radio" name="nc2-radio3" ng-model="nc2PenaltyAfter" value="specificDays" />
<input class="ggfe1" ng-model="nc2AfterDays" ng-disabled="nc2PenaltyAfter!='specificDays'" type="number" min="1" max="100" step="1" value="1" />days</div>
<div class="admin_wp-line">
<input type="radio" name="nc2-radio3" ng-model="nc2PenaltyAfter" value="immediately"/> Immediately </div>
<div class="acfv1">model 1</div>
</div>
<div style="margin-top: 20px;"><button ng-click="saveData();">Done</button></div>
............too many inputs go here
</div>
Use .$dirty! Angular will set this on every element that is bound using ng-model, automatically, when it has been changed. It will also set it on the entire form. You can access it in code like this:
if ($scope.myForm.$dirty) {
// Your code here
}
Angular will provide six useful variables on the form, and every ngModel-bound element in your form: $dirty and $pristine, $valid and $invalid, and $touched and $untouched. You can mix and match these to drive a lot of useful behaviors, and they're available both in your controller (using the expression shown above) and your template (directly).

AngularJS Form is not in HTML

I am trying to use AngularJS Validation in order to validate a simple form, however I was having troubles getting my ng-class to show the correct class based off whether or not the input was dirty or not. Then when I looked at the actual HTML of the page, the <form> tags are not even in the document at all!
<form novalidate name="infoForm">
<p>To start, provide some basic information about the project.</p>
<ul class="ulFormGeneral">
<li>
<label>Company name</label>
<input id="CompanyName" ng-class="{ cvError : infoForm.CompanyName.$dirty }" ng-model="form.CompanyName" name="CompanyName" maxlength="100" type="text" required />
</li>
</ul>
</form>
I want the cvError class to be added to this input if it is dirty, but nothing happens when I look at this in the browser. What am I doing wrong that is causing the <form> to just leave the DOM and then not work with my Angular expressions?
Welcome to the Angular world, no forms required! Here, the model is king. It looks like the problem is the ng-model and ng-class are point at different places.
Point everything at form.CompanyName (assuming that is the model name is form in the $scope):
<input id="CompanyName" ng-class="{ cvError : form.CompanyName.$dirty }" ng-model="form.CompanyName" name="CompanyName" maxlength="100" type="text" required />
The ng-model binds to the $scope. When you change the input field, it is automatically updated in the $scope. No form is needed or hitting a submit button to get the data. The $scope is updated with each key stroke.
The controller should do the work of figuring out what to do with the changes in the model. For example, you can add an ng-click to a button that fires a function defined by the controller to save the model.

AngularJS: SetValidity in ng-repeat fields

I have a form that generates some fields using ng-repeat. I want to attach each independent field to set validity in case it is left empty. Is there a way to do this?
Thanks!
You need to use ng-form with your ng-repeat. I'd update your example, but you didn't give me one... so the idea is something like this:
<form name="myForm">
<div ng-repeat="item in items" ng-form="repeatForm">
<input type="text" name="foo" ng-model="item.foo" required/>
<span ng-show="repeatForm.foo.$error.required">required</span>
</div>
</form>
If you needed to access 'setValidity' on the model for some reason, you'd probably have to pass repeatForm.foo to a function either on your controller or on your scope. like ng-click="myWeirdValidationFunction(repeatForm.foo)". There's probably not much of a use case for this though.

Get "raw" value from invalid input field

I have an input field in a form with some validations. It works like a charm.
It basically looks like this:
<input
class="form-control"
type="number"
ng-model="zipcode"
ng-minlength="5"
ng-maxlength="5"
id="zipcode"
name="zipcode"
required
>
A working plunkr is here: http://plnkr.co/edit/H0h59kG75T5MGE9cAhSo?p=preview
But now I also want to react to every input change - whether valid or not. So for example if the input field contains "123" it is not valid and the value is not transferred to my model - thats fine. But I still want to get the value to do some intermediate requests to a webservice.
Any Ideas?
First call the form element in your controller, then use the $viewValue attribute :
View :
<form name="form">
<input
...
ng-model="zipcode"
ng-change="getRawValue(form)"
name="zipcode"
required
>
</form>
Controller:
$scope.getRawValue = function(form) {
var rawValue = form.zipcode.$viewValue;
}
Angular 1.3 introduced a real answer for this: allowInvalid in ngModelOptions.
Example:
<input
type="text"
name="userName"
ng-model="user.name"
ng-model-options="{allowInvalid: true}"
>
Here is what i came up with for your scenario.
Basically you can write a directive which requires ngModel (ngModelController). The ngModelController has a array of parsers which it call to parse the view value in a pipeline manner. If validation fail these parsers do not update the model. If you inject a custom parser at the start of this parsers array, you can get the each view change value and do anything you want with it.
See my plunkr here http://plnkr.co/edit/ruB42xHWj7dBxe885OGy?p=preview (See console)
The basic code would be
ngModelCtrl.$parsers.splice(0,0,(function (viewValue) {
console.log("The view value is:"+viewValue)
return viewValue;
}));
Also see ngModelController documenation

Resources