i am using ngMessages to validate a form , which is dynamically generated using ngRepeat.ngMessages is working fine but i want to display validation error messages only submit button is clicked.I am using ng-if for checking
submit button clicked and current form field is invalid . but i am getting angular compiler error , i think it is something to do with constructing the control name dynamically.
can any one suggest what is wrong with following markup.
<div ng-repeat="item in Data" class="container-fluid">
<ng-form name="fm">
<div class="row">
<div class="col-md-10">
<h2>{{ item.headerName}}</h2>
</div>
</div>
<div class="row" ng-repeat="it in item.items">
<div class="col-md-8">
<div class="form-group">
<label for="''{{ it.name}}''" class="col-xs-4 control-label"> {{ it.name}}</label>
<div class="col-xs-2">
<select name='{{"yOrNo" + $parent.$index + $index}}'
id='{{"yOrNo" + $parent.$index + $index}}'
class="form-control"
data-ng-disabled="false"
ng-model="it.yesorNo"
ng-options="yno.id as yno.value for yno in lookups.yno"
ng-required="true"></select>
<div class="messages" ng-messages="fm.yOrNo{{$parent.$index}}{{$index}}.$error" ng-if="fm.yOrNo{{$parent.$index}}{{$index}}.$error && submitClicked" >
<div class="error-message" ng-message="required">* required.</div>
</div>
</div>
</div>
</div>
</div>
</ng-form>
</div>
Your ng-form needs a unique name per iteration, so instead of:
<ng-form name="fm"> try something like:
<ng-form name="fm{{$index}}">
note that all references to that name=fm{{$index}} will now needs to be adjusted accordingly, E.G: this: fm.yOrNo{{$parent.$index}}{{$index}}.$error will need to become this: fm{{$parent.$index}}.yOrNo{{$parent.$index}}{{$index}}.$error
Related
Below is my code to show a text box and a button next to it for uploading a file using ng-file-upload. I am trying to show the respective validation error messages like mandatory field,file size limit and acceptable file types. I am able to successfully show the error messages for required field and file size but not for acceptable file types which means
<div ng-message="accept">File format must be {{ vm.fileaccept }}</div> is not working. I am setting vm.fileaccept in the controller as vm.fileaccept = '.pdf,image/*';
<form name="uploadForm" ng-submit="vm.submitFile()" novalidate>
<div layout="row" flex="100">
<div layout="column" flex="95">
<md-input-container>
<input type="text" readonly name="filename"
class="form-control" ng-model="vm.filename" required/>
<div class="errors"
ng-show="uploadForm.$submitted || uploadForm.filename.$dirty"
ng-messages="uploadForm.filename.$error">
<div ng-message="required">Required</div>
</div>
<div class="errors"
ng-show="uploadForm.file.$error"
ng-messages="uploadForm.file.$error">
<div ng-message="maxSize">File size cannot exceed 1MB</div>
<div ng-message="accept">File format must be {{ vm.fileaccept }}</div>
</div>
</md-input-container>
</div>
<div layout="column" flex="5">
<md-input-container>
<button
ngf-select="vm.selectFile($file, $invalidFiles)" ng-model="file"
name="file" ngf-accept="vm.fileaccept" ngf-pattern="vm.fileaccept"
ngf-min-height="100" ngf-max-size="1MB">
<i class="fa fa-folder-open-o"></i></button>
</md-input-container>
</div>
</div>
</form>
I don't know the reason exactly , the below change worked.
<div ng-message="accept">File format must be {{ vm.fileaccept }}</div>
to
<div ng-message="pattern">File format must be {{ vm.fileaccept }}</div>
I have below validation for my texboxes within ng-repeat
<div class="col-md-6 col-lg-2">
<div class="form-group">
<label for="Country{{$index}}" class="control-label required">Country</label>
<div class="input-group">
<mc-lookup-dropdown data-lookup-name="CountryType" required data-model="ContactAddress.Country" id="Country{{$index}}" name="Country{{$index}}" class="form-control"></mc-lookup-dropdown>
</div>
<div data-ng-messages="memberDemographics.demographics.$error" class="validation-errors">
<div data-ng-message="Country">{{ ContactAddress.$serverErrors.Country }}</div></div>
<div data-ng-messages="demographicsForm.{{'Country'+$index}}.$error" class="validation-errors">
<div data-ng-message="required" data-ng-show="!demographicsForm.{{'Country'+$index}}.$pristine">This Field is Required</div>
</div>
</div>
</div>
below error is thrown on pageload "rror: [$parse:syntax]
http://errors.angularjs.org/1.5.8/$parse/syntax?p0=%7B&p1=is%20not%20a%20validNaNdentifier&p2=18&p3=demographicsForm.%7B%7B'PhoneNumber'%2B%index%7D%7D.%24error&p4=%7B%7B'PhoneNumber'%2B%index%7D%7D.%24error"
i need to have expression with in ng-message since textname depends on $index of ng-repeat loop..
These lines are having errors:
<div data-ng-messages="demographicsForm.{{'Country'+$index}}.$error" class="validation-errors">
<div data-ng-message="required" data-ng-show="!demographicsForm.{{'Country'+$index}}.$pristine">This Field is Required</div>
Change this with :
<div data-ng-messages="demographicsForm['Country' + $index].$error" class="validation-errors">
<div data-ng-message="required" data-ng-show="!demographicsForm['Country'+$index].$pristine">This Field is Required</div>
From this article
You only need to wrap in braces when using Angular's templating system - the braces tell Angular to replace the value. In this case, the value of data-ng-message is an expression that is being evaluated.
it worked out by changing the html to
<div data-ng-messages="demographicsForm['Country'+$index].$error" class="validation-errors">
<div data-ng-message="required" data-ng-show="!demographicsForm['Country'+$index].$pristine">This Field is Required</div>
</div>
thankyou
I'm using ng-messages and want to know if its possible to check across multiple fields in one block of code rather than having to repeat:
So I have:
(note checkCustom is a custom directive I have wrote)
<div ng-messages="registrationForm.field1.$error" ng-if="registrationFormValid">
<span ng-message="required">please enter field 1</span>
<span ng-message="checkCustom">please check custom value</span>
</div>
and
<div ng-messages="registrationForm.field2.$error" ng-if="registrationFormValid">
<span ng-message="required">please enter field 1</span>
<span ng-message="checkCustom">please check custom value</span>
</div>
However I'd much rather something like:
<div ng-messages="registrationForm.field1.$error || registrationForm.field2.$error" ng-if="registrationFormValid">
<span ng-message="required">please enter field 1</span>
<span ng-message="checkCustom">please check custom value</span>
</div>
Is something like this possible?
Thanks
A form's controller has a handy property called $error. This is an object hash, containing references to controls or forms with failing validators, where its keys are the error names (e.g. email, required, minlength, etc) and their values are arrays of controls or forms that have a failing validator for given error name - source.
This means that we can globaly check for an error inside a form just by examining if this $error object contains a specific key name.
Have a look at this example:
angular.module('myApp', ['ngMessages']);
[ng-cloak] {
display: none !important;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css">
<div ng-app="myApp" ng-cloak>
<form name="myForm">
<div class="form-group">
<h3>Validation messages:</h3>
<div ng-messages="myForm.$error" multiple>
<div ng-message="required" class="alert alert-danger">There's at least one <strong>required</strong> field</div>
<div ng-message="minlength" class="alert alert-danger">There's at least one field which doesn't fulfill the <strong>minlength</strong> condition</div>
<div ng-message="email" class="alert alert-danger">The form contains an invalid <strong>email</strong> input</div>
</div>
</div>
<div class="form-group">
<label>Required Input 1</label>
<input type="text" ng-model="myModel1" required>
</div>
<div class="form-group">
<label>Required Input 2</label>
<input type="text" ng-model="myModel2" required>
</div>
<div class="form-group">
<label>Required Input 3 which has min-length="3"</label>
<input type="text" ng-model="myModel3" required ng-minlength="3">
</div>
<div class="form-group">
<label>Required Input 4 which is type="email"</label>
<input type="email" ng-model="myModel4" required>
</div>
</form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.3/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.3/angular-messages.min.js"></script>
If you don't want to add same messages in all the blocks and add it in a single place you can do something like this:
Add all the messages in a file
<!-- remote file: error-messages.html --><div ng-message="required">please enter field 1</div>
<div ng-message="checkCustom">please check custom value</div>
Just include that file where ever you want.
<div ng-messages="registrationForm.field1.$error" ng-messages-include="error-messages.html">
</div>
So the code is reused. For a different error message override that message inside the block.
For more information check this amazing blog post.
I don't think you can add two fields in a single ng-messages block.
Just use
<div ng-if="registrationForm.field1.$error.required || registrationForm.field2.$error.required">
<span class="required">please enter field 1</span>
</div>
I have a simple code :
<div class="row" ng-repeat="aDiagnosis in diagnosisListForPrescription">
<div class="col-md-4 padding-right-zero" id={{aDiagnosis.rowIndex}}>
<input class="form-control" name="aDiagnosisName" ng-model="aDiagnosis.Name" ng-disabled="true">
</div>
<div class="col-md-4 padding-right-zero form-group" show-errors id={{aDiagnosis.rowIndex}}>
<input class="form-control" name="aDiagnosisResult" ng-maxlength="200" ng-model="aDiagnosis.Result" />
<p class="help-block" ng-if="form.aDiagnosisResult.$error.maxlength">Too Large</p>
</div>
</div>
and use $scope.form.$valid to generate the error message.
But problem is since use ng-repeat every time it finds the same name and when i want to generate second list by clicking a button ,,first error message is gone and error-message now works on the second text (obviously).
So How can i generate error-message each and every time dynamically ,,so every text form in ng-repeat,it has it's own error-message.
You can generate dynamically name attribute of your inputs in ng-repeat. For example, you can put $index (or id of your objects or whatever you want) to generate unique name for your inputs.
<div class="row" ng-repeat="aDiagnosis in diagnosisListForPrescription">
<div class="col-md-4 padding-right-zero" id={{aDiagnosis.rowIndex}}>
<input class="form-control" name="aDiagnosisName-{{$index}}" ng-model="aDiagnosis.Name" ng-disabled="true">
</div>
<div class="col-md-4 padding-right-zero form-group" show-errors id={{aDiagnosis.rowIndex}}>
<input class="form-control" name="aDiagnosisResult-{{$index}}" ng-maxlength="200" ng-model="aDiagnosis.Result" />
<p class="help-block" ng-if="form['aDiagnosisResult-' + $index].$error.maxlength">Too Large</p>
</div>
</div>
Example on plunker.
in the following code I have one drop-down list (serviceSmallId) for type of service.
It is populated using model info.
There is a second field check-box which should only be visible when drop-down has a selected value of 'Weekly'. I am trying to use ng-show/ hide of angular.
I tried to search for possible solutions but no luck.
Can anyone please guide me what I am doing wrong.
<section id="scrubber-view" class="mainbar" data-ng-controller="scrubber as vm">
<section class="matter">
<div class="container">
<div>
<button class="btn btn-info" ng-click="vm.goBack()"><i class="fa fa-arrow-left"></i>Back</button>
<button class="btn btn-info" ng-click="vm.cancel()" ng-disabled="!vm.canSave"><i class="fa fa-undo"></i>Cancel</button>
<button class="btn btn-info" ng-click="vm.save()" ng-disabled="!vm.canSave"><i class="fa fa-save"></i>Save</button>
<span ng-show="vm.hasChanges" style="color:orange" class="dissolve-animation ng-hide"><i class="fa fa-asterisk"></i></span>
</div>
<div class="row">
<div class="widget wblue">
<div data-cc-widget-header title="{{vm.title}}" subtitle="{{vm.scrubber.scrubberId}}"></div>
<form class="form-horizontal">
<div class="form-group">
<label for="serviceSmallId" class="col-sm-2">Service</label>
<div class="col-sm-4">
<select class="form-control" id="serviceSmallId" ng-model="vm.scrubber.serviceSmallId"
ng-options="item.dataLookupId as item.description for item in vm.serviceSmalls | orderBy:['sortOrder','description']">
</select>
</div>
</div>
<div class="form-group" ng-show="vm.scrubber.serviceSmallId.value=='Weekly'">
<input class="form-control" type="checkbox" id="fullyFlanged" value="Bar" />
</div>
</form>
</div>
</div>
</div>
</section>
</section>
There probably is a more elegant "angular way" solution,
but I updated you code to work here - http://jsbin.com/tupisoriho/1/edit?html,js,output
Explanation of changes
Provided ng-show a value vm.checker
added ng-change to the select element and gave it a function checkerGo which tested to see if dropdown == 'weekly', if yes change vm.checker
Update
there is a more "angular way" - using expressions!
As per #Omri Aharon fiddle/comment below.
You don't need to get the value property because a ng-model don't hold the element but the value itself;
<div class="form-group" ng-show="vm.scrubber.serviceSmallId.value=='Weekly'">
must be
<div class="form-group" ng-show="vm.scrubber.serviceSmallId == 'Weekly'">
EDIT: In your case vm.scrubber.serviceSmallId will contain the ID and not the description Weekly. I suggest you to use ng-change directive to call a function in your controller that will find the item based on ID and set in the controller to be visible for ng-show.
<select class="form-control" id="serviceSmallId" ng-model="vm.scrubber.serviceSmallId"
ng-options="item.dataLookupId as item.description for item in vm.serviceSmalls | orderBy:['sortOrder','description']"
ng-change="vm.selectObj()">
vm.selectObj() will find and set the current selected object in the scope to an controller variable (ex.: vm.selectedItem) and:
<div class="form-group" ng-show="vm.selectedItem.description=='Weekly'">