Can I concatenate within a directive declaration in AngularJS? - javascript

I have a form with an ng-repeat directive. I'm using ng-show to display validation error messages. I'm attempting to add a validation message within the ng-repeat directive, but I'm having trouble. This is what I have so far:
<form name="rentalApp" ng-controller="RentalAppCtrl">
<label for="name">Full Name</label>
<input id="name" name="name" ng-model="app.name">
<div ng-show="rentalApp.name.$invalid">Please enter your name</div>
<div ng-repeat="history in app.history">
<label for="address{{ $index }}">Street Address</label>
<input id="address{{ $index }}" name="address{{ $index }}" ng-model="history.address">
<div ng-show="rentalApp.('address' + $index).$invalid">Please enter an address</div>
</div>
</form>
As you can see, I am using the $index variable to make sure my IDs and names are unique.
In the rest of my form I'm doing something along the lines of:
<div ng-show="rentalApp.whatever.$invald">Error Message</div>
What I'm having trouble with is that within the ng-repeat directive, the indexes are dynamic. I've been fiddling around with this for a while, and the closest I think I've gotten to a solution is this line:
<div ng-show="rentalApp.('address' + $index).$invalid">Please enter an address</div>
However that doesn't work.
How can I properly concatenate the word "address" with the $index variable, to create a string along the lines of address0, which can then be used in my ng-show directive to determine if the form element is invalid? Or, alternatively, am I going about this completely wrong (not the "Angular way")?
EDIT
I'm looking at the rentalApp object from the console, and AngularJS is not evaluating the name attribute as I would expect. Specifically, the rentalApp object contains a address{{ $index }} object, instead of address0. So it looks like I can't use the expression {{ $index }} within the name attribute.

UPDATE
I make a research and find out it is not possible to give dynamic value to name besides create a custom directive for it...
but there is a solution for you to validate dynamic form with ng-form directive for each individual ng-repeat element...
<div ng-repeat="history in app.history">
<ng-form name="addressForm">
<label>Street Address</label>
<input name="address" ng-model="history.address" ng-required="true">
<div ng-show="rentalApp['address' + $index].$invalid">Please enter an address</div>
<span class="alert error" ng-show="addressForm.address.$invalid">Please enter an address</span>
</ng-form>
</div>
and here is your PLUNKER...

Just put:
<input name="{{input.name}}"></input>

Related

AngularJS ng-message directive always showing message

I am trying to set the select field in the view to be required. So I'm having the below tags in my view.html
<form name="homeForm">
<div class="form-group col-md-6 md-padding">
<div>
<label style="font-size: medium">Laboratory Name</label>
<select name="labName" class="form-control" ng-model="request.labName" required>
<option ng-repeat="lab in labList" value="{{lab.id}}">{{lab.value}}</option>
</select>
<div style="color:maroon" ng-messages="homeForm.labName.$error"
ng-if="homeForm.requestTypeName.$touched">
<div ng-message="required">This field is required</div>
</div>
</div>
I was hoping the This field is required will show up only when there is no data selected. But irrespective of the field has data or not This field is required shows up like below
Is there something I am missing here
You need to set the same input name in your input and in your ng-message. Doing this, you don't even need to have ng-if. For example:
<form name="form">
<input name="fullname" type="text" ng-model="fullname" required/>
<div ng-messages="form.$submitted && form.fullname.$error">
<p ng-message="required" class="help-block">This field is required</p>
</div>
</form>
In this case I am using form.$submitted. You can remove that, replace it with touched/dirty or whatever. The principle is the same.
The ng-messages directive is in a separate library module and must be included as a dependency.
Example
<script src="//unpkg.com/angular/angular.js"></script>
<script src="//unpkg.com/angular-messages/angular-messages.js"></script>
JS
angular.module("app",["ngMessages"])
For more information, see AngularJS ngMessages Module API Reference.
You are using homeForm.requestTypeName in the ng-if, and there is no input control named requestTypeName, i guess you must use homeForm.labName as you use in the ng-message attribute.
Basically, change the ng-if to ng-if="homeForm.labName.$touched"
TL;DR;
You could use as well the homeForm.labName.$error.required for checking if actually the end user has passed away that field without entering some input.
Source: https://docs.angularjs.org/api/ng/directive/ngRequired

What's wrong with my use of ng-class?

I'm using ui-router and the view below accesses the controller using the 'Controller As' syntax. I'm adding the 'invalid' class onto the 'shift'-radios container. When form loads you can see both validation required messages (for requestDate and shift). When requestDate and shift are set validation messages disappear. Form's $valid is true. The only problem is that the 'invalid' class on the radio-wrapper div stays.
What am I doing wrong?
<form novalidate ng-submit="_form.$valid && formCtrl.getFormData()" name="_form">
<div class="datepicker-wrapper clearfix">
<datepicker date-format="yyyy-MM-dd">
<input required ng-model="formCtrl.requestDate" name="requestDate" type="text" />
</datepicker>
</div>
<div ng-messages="_form.requestDate.$error" role="alert">
<div ng-message="required">Введите дату</div>
</div>
<div class="radio-wrapper clearfix" ng-class="{invalid: _form.shift.$error}">
<div ng-repeat="shift in formCtrl.shifts" class="item half-width pull-left">
<label for="<% shift.name %>">
<input required ng-model="formCtrl.currentShift"
name="shift"
ng-value="shift"
id="<% shift.name %>"
type="radio" />
<span class="text"><span ng-bind="shift.text"></span></span>
</label>
</div>
</div>
<div ng-messages="_form.shift.$error" role="alert">
<div ng-message="required">Укажите смену</div>
</div>
<!-- other inputs... -->
</form>
I think you need to use the $invalid property, which is a boolean, instead of the $error property, which is a hash.
See: https://docs.angularjs.org/api/ng/type/ngModel.NgModelController
Your ng-class definition is checking the wrong property of the form controller. You are checking the truthyness of _form.shift.$error. This object will always exist, even if there are no validation errors. When you don't have any errors, the value of _form.shift.$error is empty object {} which is truthy.
You should instead check the _form.shift.$invalid property which will properly update whether there are any problems with that form field.
There is no _form.shift. The input shift is declared inside an ng-repeat so it is a property on the _form.
To fix you could for example, move your ng-class inside the ng-repeat and reference the shift using ng-form to create a sub-grouping:
<div ng-repeat="shift in formCtrl.shifts" ng-form='nestedShiftForm'>
<div ng-class="{invalid: nestedShiftForm.shift.$error}">
<input name="shift" />

Accesing $pristine property of input without form in Angular?

Say I have the following HTML...
<div class="row">
<div class="col-xs-3 align-right">
<p>Email</p>
</div>
<div class="col-xs-7">
<input type="text" class="form-control" ng-model="registrationForm.email.value"/>
<span class="error-label" ng-hide="registrationForm.email.valid"><span class="glyphicon glyphicon-remove"></span>Must be a valid email!</span>
</div>
</div>
This bit of HTML creates an email field, with an error label that is shown if the email provided is invalid. This works perfectly, and is not part of my question.
I would like to slightly alter the behavior of this label. When the user first visits the form, I don't want to display the error label unless the user has changed the value of the form input.
It seems like the $pristine and $dirty properties are the key, but I'm confused on how to go about using them. If I try to access them of properties of email.value (I.E. registrationForm.email.value.$pristine) the property seems to be undefined.
I would like to avoid enclosing these inputs in an HTML form. Is there still a way I can retain use of these properties, and if so, how?
When you create your <form> element, it will create a $scope variable with the name of your form. For example:
<form name="regForm">
<div class="row">
<div class="col-xs-3 align-right">
<p>Email</p>
</div>
<div class="col-xs-7">
<input type="text" class="form-control" name="email" ng-model="registrationForm.email.value"/>
<span class="error-label" ng-hide="registrationForm.email.valid"><span class="glyphicon glyphicon-remove"></span>Must be a valid email!</span>
</div>
</div>
</form>
You can access the $pristine using $scope.regForm.email.$pristine.
Without a <form>, simply use ng-form, which will give you the functionality of the form, without needing an actual <form> element. See this post for more information.

ngMessages not working correctly with nested input

I have an input field that is nested within another <div> element, and I am trying to use ngMessages on that inside input field, but I can't seem to get it to validate correctly.
<div class="form-group" ng-model="object.idnumber" ng-hide="condition.userObjectsHidden">
<label class="form-control-label col-lg-12">ID Number</label>
<div class="col-lg-12">
<input type="text" name="idnumber" placeholder="111001111"
ng-model="user.idnumber"
ng-pattern="idpattern"
class="form-control input-lg"
required="required"></input>
<div ng-messages="idnumber.$error" ng-if="idnumber.$dirty">
<p ng-message="pattern">You are wrong!</p>
</div>
</div>
</div>
I'm not sure if it matters in terms of functionality where the <div ng-messages...> tag is, but I have also tried having it completely outside of this element with the same results. If I understand Angular and ngMessages correctly, I need to assign ng-messages to a directive--$error in this case--that I get to by dot-walking across name assignments. As far as I know, I have done this with idnumber.$error, although to be fair, I have also tried a more extensive dot-walk by using kiosk-form.uin.$error, where kiosk-form is the name of the entire form.
I have tried both ng-message="pattern" as well as ng-message="required". Also, just for clarity, idpattern is defined in my Javascript file as a regex string. It is defined correctly.
Rename your form as kioskFormand then ng-messages ="kioskForm.idnumber.$error"

How to use ng-messages with such a input like <input name='user[name]'>

I am new to Angular, and try to use ng-messages to do something like form-validate. Now, I have no problem when I use ng-message in the following situation:
<form name='loginForm' novalidate>
<input name='user' required>
<div ng-messages=loginForm.user.$error>
<div ng-message='required'> this field is required...</div>
</div>
<form>
but when I change name attribute of input,<input name='user[name]' required>, ng-message would not work again. Is there anyone can help me?
Form name attributes CAN be populated dynamically.
Remember, name attribute reads a string, and ng-messages reads an angular expression that should be evaluated to a reference to the $error object.
Since this reference is obtained through an angular expression, it can even be a method that returns the reference.
In your case, assuming your name attribute looks like this:
<form name="loginForm">
<input name="{{ user.name }}" required />
</form>
The correct syntax should be:
<div ng-messages="loginForm[user.name].$error" ></ div>

Categories

Resources