Validation on md-chips with md-autocomplete - angularjs

I am trying to build a page that uses angular material and uses elements such as md-chips and md-autocomplete.
I want to put a validation on this md-chips so that an error message will appear if there are no chips and a submit button is clicked, similar to the md-input-container.
For the md-input-container my code is as follows
<md-input-container class="md-block" flex-gt-sm>
<label>Title</label>
<input md-maxlength="100" maxlength="100" required type="text" name="bookTitle" ng-model="bookCtrl.book.name">
<div ng-messages="bookForm.bookTitle.$error" role="alert">
<div ng-message-exp="['required', 'maxlength']">
Book title is required and it should not exceed 100 characters.
</div>
</div>
</md-input-container>
And an alert will appear if the validations are not met. How can I do something similar to the md-chips with md-autocomplete that has the following code
<md-chips name="bookAuthors" ng-model="bookCtrl.book.authors" md-autocomplete-snap
md-separator-keys="bookCtrl.keys"
md-transform-chip="bookCtrl.transformChip($chip)"
md-require-match="bookCtrl.authorAutocompleteRequireMatch">
<md-autocomplete
md-selected-item="bookCtrl.selectedAuthor"
md-search-text="bookCtrl.searchAuthor"
md-items="author in bookCtrl.querySearch(bookCtrl.searchAuthor, bookCtrl.bookAuthors)"
md-item-text="author.name"
placeholder="Author">
<span md-highlight-text="bookCtrl.searchAuthor">{{author.name}}</span>
</md-autocomplete>
<md-chip-template>
<span>{{$chip.name}}</span>
</md-chip-template>
</md-chips>
What can be added to the md-chips in order to perform validation?

Create div block outside of md-chips block and add red color. It will work similarly
<div ng-messages="{test:true}" ng-show="true">
<div ng-message="test" style="color: rgb(221,44,0); font-size:12px">errroro123</div>
</div>

Related

Show server side validation message in angularjs material md-input-container with ng-messages

I have a form with some inputs which are in md-input-container. Each input have some validation message with ng-messages directive:
<form name="ctrl.myForm" layout="column" ng-submit="addUser(model)">
<input hide type="submit" />
<div layout="column" layout-padding>
<md-input-container>
<label translate>Username</label>
<input name="username" ng-model="model.username" type="text" required>
<div ng-messages="ctrl.myForm.username.$error">
<div ng-message="required" translate>This field is required.</div>
<div ng-message="unique" translate>Username is used before.</div>
</div>
</md-input-container>
<md-input-container>
<label translate>Email</label>
<input name="email" ng-model="model.email" required>
<div ng-messages="ctrl.myForm.email.$error">
<div ng-message="required" translate>This field is required.</div>
<div ng-message="email" translate>Email is not valid.</div>
</div>
</md-input-container>
</div>
<div layout="row">
<span flex></span>
<md-button
class="md-raised"
ng-click="cancel()">
<wb-icon>close</wb-icon>
<span translate>Cancel</span>
</md-button>
<md-button
class="md-raised"
ng-click="addUser(model)">
<wb-icon>done</wb-icon>
<span translate>Add</span>
</md-button>
</div>
</form>
In my controller, I have a function named addUser(model) which send given data to server and receives some validation codes. I set appropriate keys in $error objects but relative messages are not show. I set keys as following if I get error from server:
function addUser(model){
$myService.newUser(model)//
.then(function(user) {
// user is created successfully.
}, function(error) {
ctrl.myForm.$invalid = true;
ctrl.myForm.username.$error['unique'] = true;
ctrl.myForm.email.$error['email'] = true;
});
}
I expect when I set keys as true related messages appear in the form but message are not shown. In this time if I change value of a field related message of that field is shown! I could not find problem.
Read here https://docs.angularjs.org/guide/forms about $asyncValidators, there are some examples also. (ctrl.$asyncValidators.username=... etc.)
In few words:
Angularjs built-in validation requires you to write and add validators. You should not control $invalid, $error fields manually (Thats why they have $ prefix).
Angularjs material also follow this approach.
P.S. reason why lines like ctrl.myForm.$invalid = true; wont work consistently is quite simple - angularjs next validation run will set it back to false

"Required" validation not disabling submit in AngularJS

I have a form that is still running the submit code even if required fields have not been filled out. In Chrome it will pop up with "please fill out this field", but only on text inputs (not dropdowns) and it still runs the submit method. Am I missing something really obvious?
<form name="newForm">
<div class="section">
<div layout="row" class="inputRow">
<label for="itemA">ITEM A</label>
<input flex class="lineInput" ng-model="vm.contract.itemA" name="itemA" id="itemA" type="text" required />
<label for="itemB">ITEM B</label>
<select flex ng-model="vm.contract.contractType" name="itemB" id="itemB" required>
<option ng-repeat="type in vm.typeList">{{type}}</option>
</select>
<md-checkbox class="md-primary" aria-label="Checkbox No Ink" ng-model="vm.contract.itemC" name="itemC" id="itemC">
ITEM C
</md-checkbox>
</div>
<div layout="row" class="inputRow">
<label for="itemD">ITEM D</label>
<md-datepicker flex ng-model="vm.contract.itemD" id="itemC" name="itemC" md-placeholder="Enter date" required></md-datepicker>
<label for="itemE">ITEM E</label>
<md-datepicker flex ng-model="vm.contract.itemE" id="itemE" name="itemE" md-placeholder="Enter date"></md-datepicker>
</div>
</div>
<md-button type="submit" data-ng-click="vm.save()">Save and continue</md-button>
</form>
In your vm.save function inside the controller you have to put something like this:
if ($scope.newForm.$valid){
execute your code....
}
Hope it helps =)
If you want to disable Chrome doing it's own validation, and instead designing your own (for dropdowns for example) you need to include the novalidate attribute to your form.
Second, as Gustavo pointed out, your form has $valid/$invalid properties attached by angular, which can be used in many different ways:
Disable the save button:
<md-button ng-disabled="newForm.$invalid" type="submit" data-ng-click="vm.save()">Save and continue</md-button>
Moving the save function to the form using ng-submit
This allows you to submit by pressing enter, better than using ng-click IMO.
<form name="newForm" ng-submit="newForm.$valid && vm.save()">
Combining ng-disabled and ng-submit
<form name="newForm" ng-submit="vm.save()">
<md-button ng-disabled="newForm.$invalid" type="submit">Save and continue</md-button>
</form>
which is the best UX IMO
Using it to controller
if ($scope.newForm.$valid){
execute your code....
}

same ng message displaying multiple times

I am using angular version 1.5.5 and recently upgraded to angular material 1.1.0. After upgrading I started facing few issues in ng messages. Initially ng messages was not displaying. I fixed it by adding below class by referring to git issue
md-input-container .md-input-message-animation:not(.ng-animate) {
opacity: 1;
margin-top: 0px;
}
Now same ng message is displaying multiple times.
<div class="inputbox-area" ng-form='subForm'>
<md-input-container class="md-block" ng-repeat="item in dg.inputArr">
<label>Level {{$index+1}}</label>
<input md-maxlength="32" maxlength="32" ng-change="dg.showErrors = false" name="{{item.Level}}" required ng-model="item.Name" ng-pattern="/^[-a-zA-Z0-9,._' ]*$/" type="text">
<div ng-messages="subForm[$index+1].$error" ng-if="dg.showErrors">
<div ng-message="required">Level {{$index+1}} is mandatory</div>
<div ng-message="md-maxlength">should be less than 32 characters long.</div>
<div ng-message="duplicate">Level {{$index+1}} is a duplicate name</div>
<div ng-message="pattern" class="my-message">Level {{$index+1}} is an invalid name</div>
</div>
</md-input-container>
</div>
Any suggestions where I am going wrong?
<div class="inputbox-area" ng-form='subForm'>
<md-input-container class="md-block" ng-repeat="item in dg.inputArr">
<label>Level {{$index+1}}</label>
<input md-maxlength="32" maxlength="32" ng-model-options="{ updateOn: 'submit' }" ng-change="dg.showErrors = false" name="{{item.Level}}" required ng-model="item.Name" ng-pattern="/^[-a-zA-Z0-9,._' ]*$/" type="text">
<div ng-messages="subForm[$index+1].$error" ng-if="dg.showErrors">
<div ng-message="required">Level {{$index+1}} is mandatory</div>
<div ng-message="md-maxlength">should be less than 32 characters long.</div>
<div ng-message="duplicate">Level {{$index+1}} is a duplicate name</div>
<div ng-message="pattern" class="my-message">Level {{$index+1}} is an invalid name</div>
</div>
</md-input-container>
</div>
The problem is your model getting updated each time an event fires so add ng-model-options="{ updateOn: 'submit' }" in your input box this will fire only when you submit that form
Im not 100% sure, but i think ng-messages should refer to the name of the input field like this:
ng-messages="subForm.{{item.Level}}.$error"
I dont know if this sintax is gonna work, but try it out and see if it does.

Autofocus an Input Element in AngularJs

I have a small search bar which is hidden initally. With a ng-click i set "filter.show" to true and the searchbar becomes visible. As soon as this happens i want the text input inside to be focused automatically.
I'm using Angular 1.5 and Angular Material and found the focus-me option as presented below. But this doesn't work somehow and I don't understand what's the problem. Maybe someone can help me.
The html presented below uses the same controller for the button and the input.
<md-toolbar class="md-table-toolbar md-default" ng-show="filter.show && !selected.length" aria-hidden="false">
<div class="md-toolbar-tools">
<md-icon md-svg-icon="magnify"></md-icon>
<form flex="" name="filter.form">
<md-input-container class="md-block" flex="" style="margin-bottom:0">
<label>Search</label>
<input type="text" focus-me="filter.show" ng-model="query.filter" ng-model-options="filter.options" aria-invalid="false">
</md-input-container>
</form>
<button class="md-icon-button md-button md-ink-ripple" type="button" ng-click="removeFilter()">
<md-icon md-svg-icon="close"></md-icon>
<div class="md-ripple-container"></div>
</button>
</div>
</md-toolbar>

unable to compare ng-model value and value of radio button and "ng-show" a message

In the form I am designing, I would like to show a < input="date"> field for anniversary-date if the user selects a radio button with value = "married".
For now, I have replaced the same with a div saying "Anniversary date input will appear here".
My problem is that, user.maritalStatus == 'married' is always set to false.
I know this because ng-show doesn't show the message. ng-hide shows this message.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="form-group">
<div class="btn-group col-md-6 col-md-offset-4" data-toggle="buttons">
<label class="btn btn-default">
<input type="radio" name="maritalStatusRadioBtn" value="single" data-ng-model="user.maritalStatus">Single
</label>
<label class="btn btn-default">
<input type="radio" name="maritalStatusRadioBtn" value="married" data-ng-model="user.maritalStatus">Married
</label>
</div>
</div>
<!-- following does NOT work -->
<div data-ng-show="user.maritalStatus == 'married'">Anniversary date input will appear here</div>
I followed these examples:
http://codepen.io/SusanneLundblad/pen/iBhoJ
OnClick radio button show hide div angular js - the one answered by michael (highest upvotes)
but I am not getting it to work.
Thanks!
EDIT:
Codepen link: http://codepen.io/vipulnj/pen/KperpO
You would need to wrap your content inside <div ng-app=""> </div> if you have not already

Resources