Dynamically generating validation attribute on input using interpolation - javascript

Edit: This question is no longer relevant as of Angular version: 1.3.0-beta.12 you can now parse ng-minlength and ng-maxlength dynamic values. See: https://github.com/angular/angular.js/issues/5319
My problem is quite simple: I need to dynamically create input validation (ex. ng-minlength) using interpolation.
And doing that I am running into some issues specifically generating the validation attributes for ng-minlength and ng-maxlength. I assume this is due to them only taking constants?
Below you can see my code, the reason I am using a wrapper through outerForm is that I cannot dynamically generate the name attribute of input elements using interpolation, and that I have to wrap each set of repeated inputs in an ngForm directive and nest these in an outer form element.
So again, the problem lies in the attribute ng-minlength="field.ValidationAttributes['data-val-length-min']" not being properly set.
When I print the value directly using {{field.ValidationAttributes['data-val-length-min']}} the value appears correct.
Do I have to create a directive to parse my information, do I need to create my own min/max validation or am I simply running into a syntax error?
<form name="outerForm">
<div ng-repeat="field in logEntry.StringValues">
<ng-form name="innerForm">
<input type="text" name="foo" ng-model="item.foo" ng-minlength="field.ValidationAttributes['data-val-length-min']" required/>
<span ng-show="innerForm.foo.$error.required">required</span>
<span ng-show="innerForm.foo.$error.minlength">to short</span>
</ng-form>
</div>
</form>

Hi you can use double {} to interpolate dynamic validation rules please see here: http://jsbin.com/xayiro/1/
If you can post you field.ValidationAttributes model I can update jsbin.
HTML:
<ng-form name="innerForm">
<input type="text" name="foo" ng-model="item.foo" ng-minlength="{{validation.minlength}}" required/>
<span ng-show="innerForm.foo.$error.required">required</span>
<span ng-show="innerForm.foo.$error.minlength">to short</span>
</ng-form>
JS:
$scope.validation= {
maxlength:20,
minlength:3
};

Related

Text binding between input and span in Angular

How can I bind input texts to span innerHTML in Angular6?
ts file
...
finance_fullname: string;
...
template file
<input type="text" id="finance_fullname" [(ngModel)]="finance_fullname">
<span class="fullname" ngBind="finance_fullname"></span>
I can say most secure way would be innerText or textContent.
<span class="fullname" [textContent]="finance_fullname"></span>
<span class="fullname" [innerText]="finance_fullname"></span>
Even AngularJS were using textContent for one way binding. It only extract the model value and dump directly inside the specified html node. Even though if you pass html it will add that html as a text(decoded html) on the page.
Demo
innerHTML would also work for you, but it could be dangerous, as it will give a chance to inject malicious content on the page in form of html.
I don't know why you are reading from angularjs since you are working with angular 6.
If you want double binding just do it like this.
<input type="text" id="finance_fullname" [(ngModel)]="finance_fullname">
<span class="fullname">{{finance_fullname}}</span>
You can do it in two ways
(i) You can use [innerHTML]
<input type="text" id="finance_fullname" [(ngModel)]="finance_fullname">
<span class="fullname" [innerHTML]="finance_fullname"></span>
STACKBLITZ DEMO
(ii) Just bind using the two way data binding
STACKBLITZ DEMO
<input type="text" id="finance_fullname" [(ngModel)]="finance_fullname">
<span class="fullname">{{finance_fullname}}</span>

Angular form validation with external data binding

I have an Angular 4 form, but with the data tracked in an injected service (for reasons outside the scope of this question).
Each input looks something like...
<input name="..." [ngModel]='getVal(...)' (ngModelChange)='setVal(...)'>
...because there's extra functionality in those getters/setters.
That's working great, but I would also like to use the built-in validation. If I give my form a template reference variable...
<form id="..." #myForm="ngForm">
and look at the value of myForm, it's not tracking any of those inputs. I get that, I mean, I'm specifically telling it to track them elsewhere.
But how can I take advantage of the built in HTML5 validation? i.e. required and pattern
You can use validation like this in your html. This is template based validation as per your requirement.
Submit button will not be active till all the fields are validated.
<form (ngSubmit)="submitFunc()">
<input name="name" [ngModel]='getVal(...)' (ngModelChange)='setVal(...)'
required pattern=""> //required pattern here
<button [disabled]="!myForm.form.valid" type="submit">Submit Form </button>
</form>
You have to add required in your input field and specify pattern with a regular exression.

Angular form as variable

I have a form with a dynamic name containing fields with dynamic names.
I want to show a visual error feedback using ng-show if the field is invalid.
But since the field is set using a variable, I need to do something like:
ng-show="{{form.name}}.{{form.field.name}}.$dirty && {{form.name}}.{{form.field.name}}.$invalid"
How do I do that?
(The above code is obviously not working)
just do it not using interpolation, ng-show doesn't need it:
HTML form
<form name="testForm">
<input name="testInput" value="123">
</form>
validation ng-show:
ng-show="testForm.testInput.$dirty && testForm.testInput.$invalid"
so, in short just treat the variable name as normal and use it...

Angularjs Form/Field validation using JavaScript function without directives

Is there a way to validate a field in angular without using a directive?
For example: I want to make following validation on an input field.
If field is empty we should show "Field must contain a value" message.
if field contains alpha Numeric characters we should show "Field can contain only digits".
An EVEN number - message to the user "Value must be an even number".
I want to make following validation in a call to JavaScript function.
I googled around and saw that there is a way to use ng-valid and $error , however I was not managed to make it work.
Code below is according to one of the answers I got:
<div ng-app>
<form name='theForm' novalidate>
<input type='text' name='theText' ng-model='theText' ng-pattern='/^[0-9]+$/'/>
<span ng-show='theForm.theText.$error.pattern'>Field can contain only digits</span>
<span ng-show='theText.length<1'>Field must contain a value</span>
<span ng-show='theText%2!=0&&document.getElementsByName("theText").value!=""&&!theForm.theText.$error.pattern&&!theForm.theText.$pristine'>Value must be an even number</span>
<br/><input type='submit' value='Submit' />
</form>
I want to take what inside the last [span] and put inside a JavaScript function in order to make it more generic and eventually change only JS and not the HTML when conditions are changing
Can someone please advise? a working example would be great.
I'm surprised no one has mentioned ui-validate
$scope.isOdd = function($value){
return $value % 2;
}
...
<form name="myform">
<input ng-model="myVal" name="value" required
ng-pattern="/^[0-9]*$/" ui-validate=" 'isOdd($value)' "></input>
<pre>{{myform.value.$error|json}}</pre>
</form>
Doesn't get any simpler than that, and it's PROPER AngularJS validation (not silly watches)
Here's a working demo
Take a look at the angularjs form documentation - http://docs.angularjs.org/guide/forms . In general, it is based on the HTML5 attributes like required, min, max, etc.
To get, for example, your first requirement done - "an empty field should show "Field must contain a value" message, yo uwould do something like that:
<input type="text" ng-model="user.name" name="uName" required /><br />
<div ng-show="form.uName.$invalid">
<span ng-show="form.uName.$error.required">Field must contain a value.</span>
</div>
For digits only field you can use the pattern attribute with a matching regular expression (example: http://www.wufoo.com/html5/attributes/10-pattern.html).
For even number validation, I'm not sure - I think you'd have to go with custom validation for that (meaning you'd have to create a directive) or use the pattern attribute somehow.
Last but not least - remember to add novalidate to the <form> tag. Otherwise the browser will try to validate your fields as well and you don't want that:
<form ... novalidate>
...
</form>
I know the question is old and I know you didn't want a directive but you may consider using a directive if it's "Angular" way... Well here is my Angular-Validation. I made a project on Github and I think that it just rocks compare to whatever is/was available...I based myself on the excellent Laravel PHP Framework and made it available under Angular... It is so crazy simple, you need 2 lines 1 line of code, 1 line for the input, 1 line for error display, that's it... never more and never less!!! Enough said, let's give some examples:
<!-- example 1 -->
<label for="input1">Email</label>
<input type="text" validation="email|min_len:3|max_len:25|required" ng-model="form1.input1" name="input1" />
<!-- example 2 -->
<label for="input2">Alphanumeric + Exact(3) + required</label>
<input type="text" validation="alpha|exact_len:3|required" ng-model="form1.input2" name="input2" />
So I can define whatever amount of validation rules (already 25+ type of validators) which I want in a simple directive validation="min_len:2|max_len:10|required|integer" and the error message will always display in the next <span> Don't you guys like it already? 1 line of code for your input, 1 line of code for the error display, you can't be simpler than that...oh and I even support your custom Regex if you want to add. Another bonus, I also support whichever trigger event you want, most common are probably onblur and onkeyup. Oh and I also support multiple localization languages via JSON external files. I really added all the imaginable features I wanted into 1 crazy simple directive.
No more clustered Form with 10 lines of code for 1 input (sorry but always found that a little extreme) when the only thing you need is 2 lines, no more, even for an input with 5 validators on it. And no worries about the form not becoming invalid, I took care of that as well, it's all handled the good "Angular" way.
Take a look at my Github project Angular-Validation... I'm sure you'll love it =)
UPDATE
Another candy bonus! To make an even more smoother user experience, I added validation on timer. The concept is simple, don't bother the user while he's typing but do validate if he makes a pause or change input (onBlur)... Love it!!!
You can even customize the timer as per your liking, I've decided to default it to 1 second within the directive but if you want to customize you can call as for example typing-limit="5000" to make a 5 sec. timeout. Full example:
<input type="text" ng-model="form1.input1" typing-limit="5000" validation="integer|required" name="input1" />
<span class="validation text-danger"></span>
UPDATE #2
Also added input match confirmation validation (ex.: password confirmation), here is a sample code
<!-- input match confirmation, as for example: password confirmation -->
<label for="input4">Password</label>
<input type="password" name="input4" ng-model="form1.input4" validation="alpha|min_len:4|required" />
<label for="input4c">Password Confirmation</label>
<input type="password" name="input4c" ng-model="form1.input4c" validation="match:form1.input4,Password|required" />
UPDATE #3
Refactored the directive so that the requirement of having a <span> to display the error is unnecessary, the directive now handles it by itself, see the code change reflected on top.
DEMO
Added a live demo on Plunker
Well you can try to create a func
<span ng-show='isEven(theText)'>Value must be an even number</span>
$scope.isEven=function(data) {
if(data) {
return data%2===0
}
return true;
}
The method can either be defined on the current controller scope or on $rootScope.
Not a very angular way, as directives would be better but i think it would work.

Angular.js: update binding after manual modification

I'm only starting to dive into angular.js and have found this issue that I can't seem to get around. Consider this simple code:
<input type="text" ng-model="test">
<input type="text" value="{{test}}">
When I write in the first field, the second one is updated nicely. When I write in the second field and then go back to the first one, the binding is not updated anymore. Interestingly though, the HTML attribute value does get updated - it's just not displayed.
Equivalent (at least roughly) code in vanilla javascript does not suffer from this:
<input type="text" id="model">
<input type="text" id="binding">
<script>
var model = document.getElementById("model");
var binding = document.getElementById("binding");
model.addEventListener("keyup",function() {
binding.value = model.value;
});
</script>
Here's a fiddle for you to test both: http://jsfiddle.net/Q6b5k/
Any idea why this happens when using angular.js and how to fix this?
[EDIT] Judging by the initial replies, it appears I have not made it clear. I do not want the second field to update the first one. The binding is to be one-way only, e.g. to allow filtering or even manual corrections (such as automatic creation of a URL alias in a blog post creation form). http://jsfiddle.net/Q6b5k/1/
The value attribute is only used when rendering the initial HTML. After the page load, everything else happens in the Angular Event Loop and therefore you need to do something that event loop can pick up. You can use ng-change for what you are looking to do:
<input type="text" ng-model="test" ng-change="test2=test.toLowerCase();" />
<input type="text" ng-model="test2"">
This happens because {{value}} does not create a binding, it is used for interpolation.
The simplest solution is to use ng-model in both the fields
<div ng-app>
Angular.js:<br>
<input type="text" ng-model="test">
<input type="text" ng-model="test">
</div>
Demo: Fiddle

Categories