I'm using version 0.7.1 of angular material. I'm using the autocomplete as described here: Autocomplete demo
However, it doesn't seem to support validation logic, even though it generates a textarea: Autocomplete directive documentation
I imagine that I can add logic in the querySearch function to switch ng-valid to ng-invalid. Is this correct? If this is the case, then I need a handle on the md-autocomplete, but this is difficult, because the name attribute gets removed.
Create custom validator for autocomplete Working with reactive forms, the easiest way to solve this issue is to write a custom form validator. This function evaluates the value of a control and return a validation error if the value is a string type.
The md-autocomplete, an Angular Directive, is used as a special input control with an inbuilt dropdown to show all possible matches to a custom query. This control acts as a real-time suggestion box as soon as the user types in the input area.
Quick update, got the solution on Angular Material site (Latest release 1.0.0-), https://material.angularjs.org/latest/demo/autocomplete.
You will find that 'required' and 'ng-messages' are supported now.
<div ng-controller="DemoCtrl as ctrl" layout="column" ng-cloak>
<md-content class="md-padding">
<form ng-submit="$event.preventDefault()" name="searchForm">
<p>The following example demonstrates floating labels being used as a normal form element.</p>
<div layout-gt-sm="row">
<md-input-container flex>
<label>Name</label>
<input type="text"/>
</md-input-container>
<md-autocomplete flex required
md-input-name="autocompleteField"
md-input-minlength="2"
md-input-maxlength="18"
md-no-cache="ctrl.noCache"
md-selected-item="ctrl.selectedItem"
md-search-text="ctrl.searchText"
md-items="item in ctrl.querySearch(ctrl.searchText)"
md-item-text="item.display"
md-floating-label="Favorite state">
<md-item-template>
<span md-highlight-text="ctrl.searchText">{{item.display}}</span>
</md-item-template>
<div ng-messages="searchForm.autocompleteField.$error" ng-if="searchForm.autocompleteField.$touched">
<div ng-message="required">You <b>must</b> have a favorite state.</div>
<div ng-message="minlength">Your entry is not long enough.</div>
<div ng-message="maxlength">Your entry is too long.</div>
</div>
</md-autocomplete>
</div>
</form>
Read documentation
you need these options
You can use above as below to run yr custom validation :
Update yr template as below
template:'<span ng-show="validationCheck">yr msg here</span><md-autocomplete\
md-no-cache="noCache"\
md-selected-item="selectedItem"\
md-search-text="searchText"\
md-items="item in querySearch(searchText)"\
md-item-text="item.display"\
placeholder="search query"\
md-selected-item-change="validate2(searchText)"\
md-search-text-change="validate(searchText)">\
<span md-highlight-text="searchText">{{item.display}}</span>\
</md-autocomplete>'
and add following yr md-auto-complate controller
$scope.validationCheck=false;
$scope.validate=function(data){
$scope.validationCheck=true;
console.log('validation : '+data);
}
$scope.validate2=function(data){
console.log('validation2 :'+data);
}
I was working with same approach with the form validation using auto-complete in angular materials.But unfortunately, validation on this directive is not so smooth as input components. So I made up my mind to overcome this issue and did some R&D for this component. Please find below code snippets and they will help you out on this.
HTML:
<div ng-controller="DemoCtrl as ctrl" layout="column" ng-cloak="" class="autocompletedemoBasicUsage" ng-app="MyApp">
<md-content class="md-padding">
<form ng-submit="$event.preventDefault()" name="registerForm" novalidate>
<p>Use <code>md-autocomplete</code> to search for matches from local or remote data sources.</p>
<md-autocomplete md-input-name="Country" ng-disabled="ctrl.isDisabled" md-no-cache="ctrl.noCache" md-selected-item="ctrl.selectedItem" md-search-text-change="ctrl.searchTextChange(ctrl.searchText)" md-search-text="ctrl.searchText" md-selected-item-change="ctrl.selectedItemChange(item)" md-items="item in ctrl.querySearch(ctrl.searchText)" md-item-text="item.display" md-min-length="0" placeholder="What is your favorite US state?" ng-class="{'validate': registerForm.Country.$touched && !vm.country1}">
<md-item-template>
<span md-highlight-text="ctrl.searchText" md-highlight-flags="^i">{{item}}</span>
</md-item-template>
<md-not-found>
No states matching "{{ctrl.searchText}}" were found.
<a ng-click="ctrl.newState(ctrl.searchText)">Create a new one!</a>
</md-not-found>
</md-autocomplete>
<div class="ng-message" ng-messages="registerForm.Country.$error" ng-show="registerForm.Country.$touched" role="alert">
<div class="validate" ng-show="registerForm.Country.$touched && ctrl.country1 == ''" ng-class="{'slide': registerForm.Country.$touched && ctrl.country1 == ''}">
<span>Country field is required</span>
</div>
<div class="validate" ng-show="ctrl.country1 == null" ng-class="{'slide': ctrl.country1 == null}">
<span>Please enter valid Country</span>
</div>
</div>
<br>
<md-button class="medium-button success-button" aria-label="submit" ng-disabled="registerForm.$invalid || registerForm.$pristine || !ctrl.country1" ng-click="ctrl.registerUser()">
Submit
</md-button>
</form>
</md-content>
</div>
SCRIPT:
(function () {
'use strict';
angular
.module('MyApp',['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('DemoCtrl', DemoCtrl);
function DemoCtrl ($timeout, $q, $log) {
var self = this;
self.simulateQuery = false;
self.isDisabled = false;
// list of `state` value/display objects
self.states = loadAll();
self.querySearch = querySearch;
self.selectedItemChange = selectedItemChange;
self.searchTextChange = searchTextChange;
self.newState = newState;
function newState(state) {
alert("Sorry! You'll need to create a Constituion for " + state + " first!");
}
function querySearch (query) {
var results = query ? self.states.filter( createFilterFor(query) ) : self.states,
deferred;
if (self.simulateQuery) {
deferred = $q.defer();
$timeout(function () { deferred.resolve( results ); }, Math.random() * 1000, false);
return deferred.promise;
} else {
return results;
}
}
function searchTextChange(text) {
//$log.info('Text changed to ' + text);
if(text)
self.country1 = text.match(/^[a-zA-Z0-9\_\- ]*$/);
else
self.country1 = '';
if (text)
self.country = text;
$log.info('Item changed to ' + self.country1);
}
function selectedItemChange(item) {
if(item)
self.country1 = item.match(/^[a-zA-Z0-9\_\- ]*$/);
else
self.country1 = '';
if (item)
self.country = item;
$log.info('Item changed to ' + self.country1);
}
/**
* Build `states` list of key/value pairs
*/
function loadAll() {
var allStates = 'Alabama, Alaska, Arizona, Arkansas, California, Colorado, Connecticut, Delaware,\
Florida, Georgia, Hawaii, Idaho, Illinois, Indiana, Iowa, Kansas, Kentucky, Louisiana,\
Maine, Maryland, Massachusetts, Michigan, Minnesota, Mississippi, Missouri, Montana,\
Nebraska, Nevada, New Hampshire, New Jersey, New Mexico, New York, North Carolina,\
North Dakota, Ohio, Oklahoma, Oregon, Pennsylvania, Rhode Island, South Carolina,\
South Dakota, Tennessee, Texas, Utah, Vermont, Virginia, Washington, West Virginia,\
Wisconsin, Wyoming';
return allStates.split(/, +/g).map( function (state) {
return state;
});
}
/**
* Create filter function for a query string
*/
function createFilterFor(query) {
var lowercaseQuery = angular.lowercase(query);
return function filterFn(state) {
return (state.value.indexOf(lowercaseQuery) === 0);
};
}
}
})();
See the full example of codepen here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With