Angular1: How to reflect ng-model errors on another element? - javascript

I have a directive with the following template
<div>
<span class="label">My Label</span>
<input ng-model="name" required>
</div>
I want the label to be painted red when the input field is invalid.
How can I do that?
Currently I have another directive to sync all the errors from ngModelCtrl to the wrapping div
<div add-all-errors>
...
</div>
And the directive's link function does something like this:
const ngmodel = $element.find('[ng-model]').controller('ngModel');
$scope.$watch(()=>ngmodel.$error, addAllClasses, true);
Where addAllClasses simply makes sure the correct classes appear on the element..
I also tried just adding the same ng-model
<div ng-model="name">
...
</div>
But did not see the classes there..
any better way to do this?

This is why we use the angularjs form... I'm really not sure why people are against using a very handy feature.
I've made a plunker for you.
https://plnkr.co/edit/bGOcQjWzlRq2aTYZUYNm?p=preview
<form name="form">
<span ng-class="{red: form.name.$invalid}">Name:</span>
<input name="name" ng-model="name" required>
</form>
A little more insight of what's going on. form is added to the scope auto magically by angularjs by it's name. In this case, I named it form, however it can be any name.
Now form is an ngForm Object and adds all input field into it by their name attributes. This way we can do form.name to get another object similar to the ngForm Object. We can then use $invalid or $valid properties with ng-class.
ngForm is pretty powerful and is loaded with many cool properties and methods. Just call console.log(scope.form); You will need to put in a method and add it to ng-change to see updates.

Related

AngularJS ng-repeat input

I am trying to make comments functionality using Angular js. The problem is that when i want to write a comment for a post, the text is also writing inside other input elements (comments). I write a text inside one input, but it writes it in all inputs
So for example same is happening with this code
<div class="comments" ng-repeat="articles in [1,2,[4,5,6]]">
<div ng-repeat="comments in articles">
<div>
<input type="text" ng-model="$parent.new">
</div>
</div>
if i use new instead of $parent.new i get undefined, but when i use $parent.new and i write in one input, it also writes in other inputs.
The issue is that you are assigning all of the inputs to the same model, so your inputs are all in sync with the same object.
What you need is to assign each input to a different model. I'm guessing you need these models to be dynamic, so you should use an array as your model and track your ng-repeat by $index like so:
<div ng-repeat="comments in articles track by $index">
<div>
<input type="text" ng-model="arr[$index]">
<span ng-if="arr[$index]">
{{arr[$index]}}
</span>
</div>
</div>
Now, in your controller, you can initialize the empty arr like so:
$scope.arr = [];
Now, your inputs will be in sync with $scope.arr depending on the index they were in.
Try out this jsfiddle for an example.
This is because you've giving same model (ng-model="$parent.new") for all of the inputs What you should do to avoid this problem is assign different model to each input element. Something like
<div class="comments" ng-repeat="articles in [1,2,[4,5,6]]">
<div ng-repeat="comments in articles">
<div>
<input type="text" ng-model="comments">
</div>
</div>
Change ng-model of input to
<input type="text" ng-model="comments.comment">

Angular validators and ng-maxlength use

I've got the following div, which I want to add the bootstrap's class "has-error" if the input length is over 50 characters. This is the HTML:
<div class="form-group" ng-class="{has-error:[formData.titulo.$error]}">
<label for="inputTitulo">Título</label>
<input type="titulo" class="form-control" id="inputTitulo"
maxlength="50" ng-maxlength="50" ng-model="formData.titulo">
</div>
How can I make this work? I guess when you reach 50 characters, ng-maxlength throws a error, like the $error object, but I have no clue on what object is, how to access it, and if I have to do some more work in the controller or directive.
Any help here? I can't find any "easy" info regarding this issue and Angular validators.
edit 1:
I've seen all your responses, learned something new thanks to you, but this is still somehow not working. It currently is this way:
<div class="form-group" ng-class="{'has-error': formData.titulo.$error.maxlength}">
<label for="inputTitulo">Título</label>
<input type="titulo" class="form-control" id="inputTitulo" maxlength="50" ng-maxlength="50" ng-model="formData.titulo">
</div>
Also tested checking the length directly, as one of you suggested. But none of these solutions seem to work: it never adds the has-error class. Why?
To have the errors published on the scope, a form directive is required.
<div ng-form="form1" ng-class="{'has-error': form1.text1.$error.maxlength}">
<input name="text1" ng-model="formData.foo" ng-maxlength="50">
</div>
(Notice that the above uses the name attribute of the input to publish the form data - really, the ngModelController - on the scope)
So, the above works, and it's preferable if you do form validation. But, if you just need to check the length of some input, you don't have to use form validation - you could just check the model directly:
<div ng-class="{'has-error': formData.foo.length > 50}>
<input ng-model="formData.foo">
</div>
as you are using ng-model to make validations ,, this class ng-invalid will be added to your input
docs : https://docs.angularjs.org/api/ng/directive/ngModel
to use $error you need to access it using forms and names not ng-model ,, and the ng-class should be bound to the $error.maxlength not $error only
tutorial : https://scotch.io/tutorials/angularjs-form-validation
If you use the maxlength, a user will never be able to enter more characters than that, so you will never get the ng-maxlength error. It doesn't make sense to use maxlength and ngMaxlength together IMHO.
See the example on docs.angularjs.org/api/ng/directive/ngMaxlength (open the example in plunker and add maxlength attribute)

Angular nested ng-form causes $modelValue to not be set

I'm having a little issue with an Angular project. Firstly the $digest value in a form wasn't set to true, in certain conditions. I fixed it via this post.
So in order to fix that problem I had to put a ng-form around some parts in my form. Making it look like the following:
<div class="fim-sub-input">
<ng-form name="gender" novalidate>
<label class="fim-radio" fim-radio ng-repeat="gender in genders">
<input type="radio" name="gender" value="{{ gender.id }}" ng-model="card.gender">
<span class="fim-sub-label">{{ gender.name }}</span>
</label>
</ng-form>
</div>
This fixed my $digest problem. However now in the form, the gender property never has a $modelValue property? All other form properties still do, except the gender property, which is in a nested form doesn't have it. Is this expected behaviour?
I currently fixed it by setting the form.gender.$modelValue to the value which is in the scope's model, before I process the form. It works, but it's ugly :)
Any ideas?
not sure what you are trying, but ng-model should be gender.gender instead of card.gender.
You might still eventually get some issues since you are using ng-repeat which creates a child scope (unless you use ng-model = $parent.gender.gender)

AngularJS forms not finding input elements

At some point during the development of my app, AngularJS forms stopped working... Yes that means they used to work. That is, form elements are supposed to create their own scope with every <input /> by their name. However all my forms are now completely empty, as if I had no input elements with the name attribute. Now I can't make any sort of form validation. I've tried even the most trivial forms and still nothing:
<form name="form>
<input type="text" name="input" required />
</form>
Any suggestions as to how to debug this?
Hi to do validation your input have to have model directive please see here: http://jsbin.com/deref/1/edit
<form name="form">
<input type="text" name="foo" required ng-model="input.model"/>
<span ng-show="form.foo.$error.required">required</span>
</form>
Try console.log on the scope
console.log($scope.form);
If you have your controllers set up correctly, your form should be attached to the scope of controller.

Error: [$compile:multidir] Multiple directives [form, form] asking for 'form' controller on: <form ng-form="">

I am getting this error on a form I am building in angularjs.
`Error: [$compile:multidir] Multiple directives [form, form] asking for 'form' controller on:
<div data-ng-controller="shortlistController">
<ul>
<li data-ng-repeat="job in jobs">
<div>{{ job.role }}</div><div>{{ job.salary }}</div><div>{{ job.company }}</div>
</li>
</ul>
</div>
<form ng-form>
<input type="text" ng-model="newRole">
<input type="text" ng-model="newSalary">
<input type="text" ng-model="newCompany">
<input type="text" ng-model="newUrl">
<button>Submit</button>
</form>
Initially I had the form within data-ng-controller, I took it out to see if the controller might have been the issue..
Please ask if you think I need to post more code, I am using angulars native routing system
Each of these is more or less identical and refers to the form directive:
<form></form>
<div form></div>
<div x-form></div>
<div data-form></div>
So you can do either <div form></div> or simply <form></form>, and in both cases they refer to the same form directive. But <form form></form> would be redundant.
The ngForm directive which you mention is actually an alias for the form directive above, and can be referenced using any of these:
<ng-form></ng-form>
<div ng-form></div>
<div x-ng-form></div>
<div data-ng-form></div>
So in your case, you were doing <form ng-form></form>, which is really the same as <form form></form>, which is why you're getting that error.
This page explains in more detail all the different ways to reference directives:
http://docs.angularjs.org/guide/directive
BTW, a benefit (sometimes) to using the <div ng-form></div> format is that you can do nested forms, whereas you can't do nested forms using just the <form> tag.
You don't need the ng-form if you're using <form> as it automatically is hooked up to the ng-form directive. You use either or, not both.
I encountered the same problem when I set my component name to form.
angular.module("testApp").component("form", {
...
});
Effect was the similar as in #user553086 answer. Change component's name solves the problem.

Categories

Resources